diff --git a/.changeset/config.json b/.changeset/config.json new file mode 100644 index 000000000..91b6a9512 --- /dev/null +++ b/.changeset/config.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": "@changesets/cli/changelog", + "commit": false, + "fixed": [], + "linked": [], + "access": "restricted", + "baseBranch": "main", + "updateInternalDependencies": "patch", + "ignore": [] +} diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 52031de51..000000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.sol linguist-language=Solidity diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 3e6ab4b1d..d6173e517 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -17,4 +17,4 @@ runs: run: yarn --immutable - name: Build shell: bash - run: yarn build \ No newline at end of file + run: yarn build || yarn build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-contracts.yml similarity index 86% rename from .github/workflows/ci.yml rename to .github/workflows/ci-contracts.yml index ba93fac60..388bb8521 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-contracts.yml @@ -1,4 +1,4 @@ -name: CI +name: CI - packages/contracts env: CI: true @@ -23,7 +23,9 @@ jobs: - name: Set up environment uses: ./.github/actions/setup - name: Run tests - run: yarn test:coverage + run: | + pushd packages/contracts + yarn test:coverage - name: Upload coverage report uses: codecov/codecov-action@v3 with: diff --git a/.github/workflows/ci-token-dist.yml b/.github/workflows/ci-token-dist.yml new file mode 100644 index 000000000..76922ff9d --- /dev/null +++ b/.github/workflows/ci-token-dist.yml @@ -0,0 +1,26 @@ +name: CI - packages/token-distribution + +env: + CI: true + +on: + push: + branches: "*" + paths: + - packages/token-distribution/** + pull_request: + branches: "*" + paths: + - packages/token-distribution/** + workflow_dispatch: + +jobs: + test-ci: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up environment + uses: ./.github/actions/setup + - name: Run tests + run: yarn test \ No newline at end of file diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e-contracts.yml similarity index 89% rename from .github/workflows/e2e.yml rename to .github/workflows/e2e-contracts.yml index e13a98bab..46a6387ca 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e-contracts.yml @@ -1,4 +1,4 @@ -name: E2E +name: E2E - packages/contracts env: CI: true @@ -9,7 +9,7 @@ on: paths: - packages/contracts/contracts/** - packages/contracts/config/** - - packages/contracts/e2e/** + - packages/contracts/test/e2e/** - packages/contracts/tasks/** - packages/contracts/scripts/** - packages/contracts/hardhat.config.ts @@ -18,7 +18,7 @@ on: paths: - packages/contracts/contracts/** - packages/contracts/config/** - - packages/contracts/e2e/** + - packages/contracts/test/e2e/** - packages/contracts/tasks/** - packages/contracts/scripts/** - packages/contracts/hardhat.config.ts @@ -41,4 +41,5 @@ jobs: sed -i'' -e 's/^\(.*dev.period.*\)/# \1/' docker-compose.yaml ./test-node.bash --init --batchposters 0 --redundantsequencers 0 --detach popd + pushd packages/contracts L1_NETWORK=localnitrol1 L2_NETWORK=localnitrol2 yarn test:e2e diff --git a/.github/workflows/verifydeployed.yml b/.github/workflows/verifydeployed.yml index 07a18a52b..549d6d7ed 100644 --- a/.github/workflows/verifydeployed.yml +++ b/.github/workflows/verifydeployed.yml @@ -36,8 +36,8 @@ jobs: with: name: contract-artifacts path: | - build - cache/*.json + packages/contracts/build + packages/contracts/cache/*.json verify: name: Verify deployments @@ -54,7 +54,7 @@ jobs: name: contract-artifacts - name: Verify contracts on Defender - run: yarn hardhat --network ${{ inputs.network }} verify-defender ${{ inputs.contracts }} + run: cd packages/contracts && yarn hardhat --network ${{ inputs.network }} verify-defender ${{ inputs.contracts }} env: DEFENDER_API_KEY: "${{ secrets.DEFENDER_API_KEY }}" DEFENDER_API_SECRET: "${{ secrets.DEFENDER_API_SECRET }}" diff --git a/.gitignore b/.gitignore index b6875bdf5..ecd5f0d2c 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ cached/ # Build artifacts dist/ build/ +deployments/hardhat/ # Ignore solc bin output bin/ @@ -43,3 +44,9 @@ addresses-fork.json # Keys .keystore + +# Graph client +.graphclient + +tx-builder-*.json +!tx-builder-template.json \ No newline at end of file diff --git a/.yarnrc.yml b/.yarnrc.yml index 3186f3f07..11969f789 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1 +1,2 @@ nodeLinker: node-modules +nmHoistingLimits: workspaces \ No newline at end of file diff --git a/README.md b/README.md index 9db7a4935..f9f736fb5 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,10 @@ This repository is a Yarn workspaces monorepo containing the following packages: | Package | Latest version | Description | | --- | --- | --- | | [contracts](./packages/contracts) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fcontracts.svg)](https://badge.fury.io/js/@graphprotocol%2Fcontracts) | Contracts enabling the open and permissionless decentralized network known as The Graph protocol. | +| [eslint-graph-config](./packages/eslint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for TypeScript projects. | +| [token-distribution](./packages/token-distribution) | - | Contracts managing token locks for network participants | | [sdk](./packages/sdk) | [![npm version](https://badge.fury.io/js/@graphprotocol%2Fsdk.svg)](https://badge.fury.io/js/@graphprotocol%2Fsdk) | TypeScript based SDK to interact with the protocol contracts | +| [solhint-graph-config](./packages/eslint-graph-config) | [![npm version]()]() | Shared linting and formatting rules for Solidity projects. | ## Development @@ -65,21 +68,42 @@ $ yarn $ yarn build ``` -### Versioning a package +### Versioning and publishing packages -To version a package, run the following command from the root of the repository: +We use [changesets](https://github.com/changesets/changesets) to manage package versioning, this ensures that all packages are versioned together in a consistent manner and helps with generating changelogs. + +#### Step 1: Creating a changeset + +A changeset is a file that describes the changes that have been made to the packages in the repository. To create a changeset, run the following command from the root of the repository: ```bash -# Change directory to the package you want to version -$ cd packages/ +$ yarn changeset +``` + +Changeset files are stored in the `.changeset` directory until they are packaged into a release. You can commit these files and even merge them into your main branch without publishing a release. -# Bump the version -$ yarn version +#### Step 2: Creating a package release + +When you are ready to create a new package release, run the following command to package all changesets, this will also bump package versions and dependencies: + +```bash +$ yarn changeset version +``` + +### Step 3: Tagging the release + +__Note__: this step is meant to be run on the main branch. + +After creating a package release, you will need to tag the release commit with the version number. To do this, run the following command from the root of the repository: + +```bash +$ yarn changeset tag +$ git push --follow-tags ``` -__Note on cross referenced packages__: Bumping the version of a package that is cross referenced by another package will automatically bump the dependency version in the other package. For example, if you bump the version of `sdk` from `0.0.1` to `0.0.2`, the required version of `sdk` in the `contracts` package will automatically be bumped to `0.0.2`. Depending on the nature of the change you might need to bump (and publish) a new version of the `contracts` package as well. +#### Step 4: Publishing a package release -### Publishing a package +__Note__: this step is meant to be run on the main branch. Packages are published and distributed via NPM. To publish a package, run the following command from the root of the repository: diff --git a/package.json b/package.json index 77cd47d4f..90821c951 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,10 @@ "packageManager": "yarn@4.0.2", "workspaces": [ "packages/contracts", - "packages/sdk" + "packages/eslint-graph-config", + "packages/sdk", + "packages/solhint-graph-config", + "packages/token-distribution" ], "scripts": { "postinstall": "husky install", @@ -19,6 +22,7 @@ "test": "yarn workspaces foreach --all --parallel --verbose --interlaced run test" }, "devDependencies": { + "@changesets/cli": "^2.27.1", "@commitlint/cli": "^18.4.3", "@commitlint/config-conventional": "^18.4.3", "husky": "^8.0.3" diff --git a/packages/contracts/.eslintignore b/packages/contracts/.eslintignore deleted file mode 100644 index 02127cba1..000000000 --- a/packages/contracts/.eslintignore +++ /dev/null @@ -1,7 +0,0 @@ -build/ -cache/ -coverage/ -node_modules/ -truffle.js -cache/ -dist/ diff --git a/packages/contracts/.eslintrc b/packages/contracts/.eslintrc deleted file mode 100644 index 89b53531b..000000000 --- a/packages/contracts/.eslintrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "parser": "@typescript-eslint/parser", - "parserOptions": { - "ecmaVersion": 2020, - "sourceType": "module" - }, - "extends": ["plugin:@typescript-eslint/recommended", "plugin:prettier/recommended"], - "rules": { - "prefer-const": "warn", - "no-extra-semi": "off", - "@typescript-eslint/no-extra-semi": "off", - "@typescript-eslint/no-inferrable-types": "warn", - "@typescript-eslint/no-empty-function": "warn", - "no-only-tests/no-only-tests": "error" - }, - "plugins": [ - "no-only-tests" - ] -} diff --git a/packages/contracts/.prettierignore b/packages/contracts/.prettierignore deleted file mode 100644 index 4e76680e5..000000000 --- a/packages/contracts/.prettierignore +++ /dev/null @@ -1,4 +0,0 @@ -build -reports -cache -coverage.json \ No newline at end of file diff --git a/packages/contracts/.prettierrc.json b/packages/contracts/.prettierrc.json deleted file mode 100644 index 0b2b67edd..000000000 --- a/packages/contracts/.prettierrc.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "printWidth": 100, - "useTabs": false, - "bracketSpacing": true, - "plugins": ["prettier-plugin-solidity"], - "overrides": [ - { - "files": "*.js", - "options": { - "semi": false, - "trailingComma": "all", - "tabWidth": 2, - "singleQuote": true, - "explicitTypes": "always" - } - }, - { - "files": "*.ts", - "options": { - "semi": false, - "trailingComma": "all", - "tabWidth": 2, - "singleQuote": true, - "explicitTypes": "always" - } - }, - { - "files": "*.sol", - "options": { - "tabWidth": 4, - "singleQuote": false - } - } - ] -} diff --git a/packages/contracts/CHANGELOG.md b/packages/contracts/CHANGELOG.md new file mode 100644 index 000000000..802cff94c --- /dev/null +++ b/packages/contracts/CHANGELOG.md @@ -0,0 +1,51 @@ +# @graphprotocol/contracts + +## 6.2.1 + +### Patch Changes + +- Round up when calculating curation tax +- Round up when calculating consecutive stake thawing periods + +## 6.2.0 + +### Minor Changes + +- Update implementation addresses with GGP 31, 34 and 35 + +### Patch Changes + +- 554af2c: feat(utils): add utility to parse subgraph ids +- Updated dependencies [554af2c] +- Updated dependencies [c5641c5] + - @graphprotocol/sdk@0.5.0 + +## 6.1.3 + +### Patch Changes + +- Ensure globbing is enabled in prepack + +## 6.1.2 + +### Patch Changes + +- Correctly pass ts file list to tsc in prepack + +## 6.1.1 + +### Patch Changes + +- Use prepack to correctly prepare outputs for the published package + +## 6.1.0 + +### Minor Changes + +- Introduce changesets for versioning +- Add new staging implementations including GGPs 31, 34 and 35 +- Add new testnet implementations including GGPs 31, 34 and 35 + +### Patch Changes + +- Fixes for verifyAll and bridge:send-to-l2 hardhat tasks diff --git a/packages/contracts/TESTING.md b/packages/contracts/TESTING.md index 90f513d8d..75e9db77c 100644 --- a/packages/contracts/TESTING.md +++ b/packages/contracts/TESTING.md @@ -92,8 +92,8 @@ Scenarios are defined by an optional script and a test file: - Optional ts script - The objective of this script is to perform actions on the protocol to advance it's state to the desired one. - Should follow hardhat script convention. - - Should be named e2e/scenarios/{scenario-name}.ts. + - Should be named test/e2e/scenarios/{scenario-name}.ts. - They run before the test file. - Test file - - Should be named e2e/scenarios/{scenario-name}.test.ts. + - Should be named test/e2e/scenarios/{scenario-name}.test.ts. - Standard chai/mocha/hardhat/ethers test file. \ No newline at end of file diff --git a/packages/contracts/addresses-staging.json b/packages/contracts/addresses-staging.json index 1e5a93c89..e3708b172 100644 --- a/packages/contracts/addresses-staging.json +++ b/packages/contracts/addresses-staging.json @@ -73,10 +73,10 @@ "txHash": "0x9346e8c6133211590867ebe9bee37efb44f52175ee7ce498a57a78d1223e6357", "proxy": true, "implementation": { - "address": "0x86a16B4fE9561c1E0815c05d99AC5e94Cd23D556", - "creationCodeHash": "0x6610cab951492064988e74cc991fd687ecbdf0ce206e874d5054668328c7dcff", - "runtimeCodeHash": "0x1eb061055cfba911d6ad0f3c3ea7eeb7c1441609cb7509ca3d9aa6acb83418fb", - "txHash": "0x9e150a85a5dbbcdc931124d9f5c26937fc2c2c3c04223ad3d296f28513045e92" + "address": "0x60d946bCAC1bcd99dA79cdd37bd4cAAb1f739A1F", + "creationCodeHash": "0x2287d9023bf7d91e688e1eb029eff7657ef3b87e37b5222b01fd50985d0928f9", + "runtimeCodeHash": "0xd799b2b74e9634d6b6ef15b5710409264bed04a60f9519b9d8f05ac183199d16", + "txHash": "0xae41519e9620042b88b76a39fec00946a17cf41d47b659351a967cc86dbc1b53" } }, "SubgraphNFTDescriptor": { @@ -103,17 +103,17 @@ "txHash": "0xbd2d3f6d4fee611c5f090da74c1abcb83274fc9deb3e57f9903ce6e6eb7c3d2c", "proxy": true, "implementation": { - "address": "0x7c23d5CCbE0332eacE37BA460e1363e626F0cFCB", - "creationCodeHash": "0x6b005bdaf7534311b6dd4ae41955ed721aa0dc1c69d1c94517885ca6a3dd3ac1", - "runtimeCodeHash": "0xa4da5d616fbe18a7432551a837f9f618398cb92bcdd98164879e166aa76f5272", - "txHash": "0xfdaf70d60e83d61eb328382c707189499acc4342950fbceaa1c84d719eb3938c" + "address": "0x5792f9a70DE8c58D8df1A03E6CEc72fe1e14fc4B", + "creationCodeHash": "0xd71f45e6c194920a26f90fcec96d8c3375f02c5aef8ad90c1be24e906ffe8342", + "runtimeCodeHash": "0x68ec24512fedb866d7ba7ba6c02160317d0ca34eaacd23bddcc62d2cbcd9869c", + "txHash": "0x1b9b13111d5647b8f3f73567c00d81abc95296fb885c346a454df4f80d3cda23" } }, "StakingExtension": { - "address": "0x9291448138A18CE5329470417AE5f3cba1D974Ed", - "creationCodeHash": "0x8de9e9fe7e46fd75fee0be1fa10bc1c250532991c123db106bb3bad01ac9046b", - "runtimeCodeHash": "0xa9215542f24456fb4c63cc8684699255f85d29a0cf611d3dc7191b1445716376", - "txHash": "0x2bd6745f1cfcefce130259d6741c5f92f02e209e5b80fbc2bc0ea8b9067d6133" + "address": "0x36C27F2DFa4F3bAF609d8E53D7Dd1A5e64eA9266", + "creationCodeHash": "0x7ae74140871330ecabb7040182dc8288c2c84693393a519230036f39c2281138", + "runtimeCodeHash": "0x4994aa74e9e29c36a8158af690a245ccd1cf4d955223e5fcb1ca62810b37ed57", + "txHash": "0xe96b9221e789496baf1718190c05e54d5d4a96049acfca0158f836d0f464849f" }, "L2Staking": { "address": "0x3fC01c0E957Ca1c8C7E94Edd4497A6d6B1ED9b73", @@ -134,12 +134,12 @@ "txHash": "0x5ae51383f5ad1e434a78c2a6d5393d497be315c40287d827c63c4ca48cc66aca", "proxy": true, "implementation": { - "address": "0x68036E38b054a3dd8502Eb1eEB6bc26836ADFfaF", - "creationCodeHash": "0xd737e2909041722853ee690e60519455019ddc4d5653067c646138ac155941eb", - "runtimeCodeHash": "0xfadaa9203fb6656749bbf0013fd0870e4b9f44d88a199ed648cf950006ae73c7", - "txHash": "0x3ecae3468175a9b25303cbcc05a033be32fd3a59c14298310e44c43fe72c0f5a", + "address": "0xC4Cfde877Bc77fD93378D33Ec26330127Ed93bbE", + "creationCodeHash": "0x9319aaf6b70b423fa04ad747f004961123e7833b269f69ecff902db13b010fa2", + "runtimeCodeHash": "0x9a3f54b5f61709d40a71892f241f61fc72cf95346e5d928f1d699ea57065efc4", + "txHash": "0x1e53eadecdb33a8e90e5c9bc3d02d438dd21217c5017b596b3e51f64be4501e2", "libraries": { - "LibExponential": "0xc953f711602bD293EabFD60B48aaA62D109232E2" + "LibExponential": "0x6f6Db03f7F3bBE43669F81FD954Bd083FEdBb4a5" } } }, @@ -172,10 +172,10 @@ "txHash": "0x466f67046c81847e5d7746471ebbd255ab721c7ee85e85520254513b10745e7b", "proxy": true, "implementation": { - "address": "0x8E44bD1B2dfEAbf1efA4bDbDA98dC2F6577C03C9", - "creationCodeHash": "0xc57491ef973583304f2d179445a0cd0983c88abe321536195aa10b6602c72c05", - "runtimeCodeHash": "0x08740630f1836c12c860f717f40eeec7b4c08cb8a950f842f11fb200a3541cfd", - "txHash": "0x89ecbe0f419edf58e124459292c469482479b002835d8a30c06664943881ca67" + "address": "0x800C6152ae29C39B7fA4d40079017140d3A81fB4", + "creationCodeHash": "0xce4c47d94a33d69e03d607dd13a9ad1ed7fa730ef4a2308eb56ddd646ebaa0aa", + "runtimeCodeHash": "0x18d4a1659ccecede3d4d305ef1db4653d8f3dcbd4012f4e52200ae9f0c6c322c", + "txHash": "0x245066977ce08f06ce90add71cdf1c366bd9c8c0cb08fd6998a8ca2ac8758185" } }, "AllocationExchange": { diff --git a/packages/contracts/addresses.json b/packages/contracts/addresses.json index 28ed041de..ae66613a2 100644 --- a/packages/contracts/addresses.json +++ b/packages/contracts/addresses.json @@ -648,10 +648,10 @@ "txHash": "0x8f856e2090af3243349199f7991e01b1c28de7b70b0185d2370d8ada5ce9c97b", "proxy": true, "implementation": { - "address": "0x1B75515d958b7D18f07E5239513F1f285545168D", - "creationCodeHash": "0x352ed8700f6af5d508b8e5b2cd2908b1484b731f29733c64514aede9aa07419c", - "runtimeCodeHash": "0x508f4f423b6262c9eab7e33036493f1df44590db784b292bcc0eb2db6587bf2c", - "txHash": "0x3c346af5b60d2375d150855d95217fbcdd82bcde73dc36995450f25262a19622" + "address": "0x41Ad970e071aadbE098c17aDFCff2fF3105456Ae", + "creationCodeHash": "0x2c7b48c311e8f0cb03513d4ca4c0010132d7402f1aabb1dd65f28cdcf07255ba", + "runtimeCodeHash": "0xa750bd231f2b1ec9ffaeef4de79eddbde8aca9bdbf4c9125424eea644bf27aff", + "txHash": "0x7b03bc16b3af6a650ff866311b1f580936e8b7264ddb4c6348fb824c508d1dcb" } }, "SubgraphNFTDescriptor": { @@ -679,10 +679,10 @@ "txHash": "0xf7f2747d1aafd1684ffee7316e727475249cd358af559c6234089b72ffc25f5d", "proxy": true, "implementation": { - "address": "0x5cBDB6cfB91d435c5899Fc05741e7D371fd71667", - "creationCodeHash": "0xab7a8f4163377ef288e0bb8551051a920a83e0ec553b874f0f99b9db880d4e4a", - "runtimeCodeHash": "0x9c4fbf132be7d540c99d00475226cb1fcba2625dde67cf3be8679f2374542940", - "txHash": "0x328642997c021f8403348e999bfbada5cbbf94ae97c2f4d7e53e45fd08c201a6" + "address": "0x9B81c7C5A21E65b849FD487540B0A82d3b97b2c7", + "creationCodeHash": "0xd71f45e6c194920a26f90fcec96d8c3375f02c5aef8ad90c1be24e906ffe8342", + "runtimeCodeHash": "0x68ec24512fedb866d7ba7ba6c02160317d0ca34eaacd23bddcc62d2cbcd9869c", + "txHash": "0xfaecc9eb83958359f7440b3dbe1747c2191590acbbde920f191c94352cc0b6d7" } }, "L2Staking": { @@ -705,12 +705,12 @@ "txHash": "0xa33c0d58ddaed7e3f7381a33e3d5f63e39219863019f00d54ce2fd2446076ac7", "proxy": true, "implementation": { - "address": "0x069FaCd162023626866EfDa1C079D848575750d3", - "creationCodeHash": "0xb242871068073ca5f58cd0d7df13f13a000424582252e9cc9f73a581d31f623d", - "runtimeCodeHash": "0x799c51f69136f094239a5f69e39d1d1231dcb026788cdc5e9a6a1d0008e38728", - "txHash": "0x8819cfb1d6837ebc17537d9919f18ebd03e5b846c703ab5f5b32bdaf54c315f7", + "address": "0x4a886d3E44C7731Dcf888Da704CA5C51ed63DfC8", + "creationCodeHash": "0xa9796308a637b0bfe091f32c1019e4db8efe4bab80788c052fa334e6810c3a98", + "runtimeCodeHash": "0x19d3491cab54b2aae04d05525a532200e946ce9b55573b58f2e3e1606b4514be", + "txHash": "0xc3235306a51c20b28a8b05da69859e03a081a84c9914156c79da07dcc45b3b4e", "libraries": { - "LibExponential": "0x38f7f3F8C4fE5aab64C5cB6657217413EFcB8817" + "LibExponential": "0x208f638d8804e4ccc874ec39e240feea3dc289ee" } } }, @@ -743,10 +743,10 @@ "txHash": "0x68f08fe0a1179170c8b4c7542725d71432b4171604d7456dff824e0ec1c6cdb9", "proxy": true, "implementation": { - "address": "0x0E55B996EB7Bfc3175E883D02FF55a34f8C9986e", - "creationCodeHash": "0x2e77ad7a1627b6e04bece0fe18b3ab543ef4a2d6914f2e5e640b2c8175aca3a8", - "runtimeCodeHash": "0x0186afe711eff4ceea28620d091e3c6034fd15be05894119c74a38b020e3a554", - "txHash": "0xbb04391bd3353d6f2210e98ced779edcda954d971effcae7fd8676a94afa2655" + "address": "0x358bCB57F9893188c1f5CA4e3390C8E84dAAD9B9", + "creationCodeHash": "0xce4c47d94a33d69e03d607dd13a9ad1ed7fa730ef4a2308eb56ddd646ebaa0aa", + "runtimeCodeHash": "0x18d4a1659ccecede3d4d305ef1db4653d8f3dcbd4012f4e52200ae9f0c6c322c", + "txHash": "0xc6b7c7ac5e1b800326fdc99a12262a1528f46fbd0881b5869d7c5a1709c6e0ce" } }, "AllocationExchange": { @@ -785,10 +785,11 @@ "address": "0xa9AEb1c6f14f4244547B9a0946C485DA99047638" }, "StakingExtension": { - "address": "0xF79Ac2BD4F40c737f0BaCDa89fF40f5E821896D0", - "creationCodeHash": "0xe23c59dbfb94b0cf7ef58f654b905977624ce57eaae2fce692edb28ca3f1b3ba", - "runtimeCodeHash": "0xca8ad20187bc87e0e04a15184f529787dd23a0095047d411e1b271617a951c49", - "txHash": "0xd80b1ca833e10a261c3feb0b816a7ef6de8e5378fa5f7f382f80adc53758f6a4" + "address": "0x3bE385576d7C282070Ad91BF94366de9f9ba3571", + "constructorArgs": [], + "creationCodeHash": "0xbfc20ab9b880712ab90b5dec9d2a14c724b0bf7c20f02ede8ea76610bd41b6ef", + "runtimeCodeHash": "0xd7fdd744c7a88993435a2978876b1e4341c5e0fb4d611011bb56e8738ab2485d", + "txHash": "0xcc449d1ca1007fba76b25e987ea0d39164acf4027c10c40bd669ede1c65dc569" } }, "421613": { @@ -1084,10 +1085,10 @@ "txHash": "0xe9298239bcb3c386cf66e6dd493cf6e7cdd9771c65fa2225e0b34d17550d6805", "proxy": true, "implementation": { - "address": "0x0FeB615632ffc04e6fC5BcAc9fF1bF97DD41d0a0", - "creationCodeHash": "0x75b20d5672b72cce7cdcedaf9cb97d909851e8dbe13dfe191efb2f786c729e18", - "runtimeCodeHash": "0xc361cd723ddeb297fc805e25d8632ad364deb6a07ef363e5f435db197b551241", - "txHash": "0xb76f3db491fed5e532de7ab33ff8621466d76cfa0d11bfaa61c8ab68952b0170" + "address": "0xd90022aB67920212D0F902F5c427DE82732DE136", + "creationCodeHash": "0x2287d9023bf7d91e688e1eb029eff7657ef3b87e37b5222b01fd50985d0928f9", + "runtimeCodeHash": "0xd799b2b74e9634d6b6ef15b5710409264bed04a60f9519b9d8f05ac183199d16", + "txHash": "0x436bcf91fed712dc8d54f449726b2078fb63cd770f90b492a9622efac5817762" } }, "SubgraphNFTDescriptor": { @@ -1114,17 +1115,17 @@ "txHash": "0x137140783a99a3e9a60048d607124626ca87e2b972e8cc05efb41ac87c3cbcc4", "proxy": true, "implementation": { - "address": "0xb3fc82BcC8c793252460E574a2D604DCE0F06D29", - "creationCodeHash": "0x94711fb5bbc7fc4430b7e2d0d28209777427063ee1a35ca602357f0bf6c4cad7", - "runtimeCodeHash": "0x9d6890368edc21a1f53d7fe6baab12d408cb0e8d6c45aeb8479fc064de748055", - "txHash": "0x7c1cbe942df027f1eaeff0eba2fed242d67b916356a5315de07e10a864f403d7" + "address": "0x00CBF5024d454255577Bf2b0fB6A43328a6828c9", + "creationCodeHash": "0xd71f45e6c194920a26f90fcec96d8c3375f02c5aef8ad90c1be24e906ffe8342", + "runtimeCodeHash": "0x68ec24512fedb866d7ba7ba6c02160317d0ca34eaacd23bddcc62d2cbcd9869c", + "txHash": "0x54619944731edec530b7b0cd587f9c2faae332aa1671fe5e8d7e7e5c7e291a77" } }, "StakingExtension": { - "address": "0x876fB4B13D7Ed146757D3664B7E962b36936001C", - "creationCodeHash": "0xe23c59dbfb94b0cf7ef58f654b905977624ce57eaae2fce692edb28ca3f1b3ba", - "runtimeCodeHash": "0xca8ad20187bc87e0e04a15184f529787dd23a0095047d411e1b271617a951c49", - "txHash": "0xb2684880fbccbf085b6a4f339f1848ff5559ea49be5a1025ded7d2bd9ba4c3cf" + "address": "0x05709dd705A5674346B7206a2bC657C8bAb3301B", + "creationCodeHash": "0x7ae74140871330ecabb7040182dc8288c2c84693393a519230036f39c2281138", + "runtimeCodeHash": "0x4994aa74e9e29c36a8158af690a245ccd1cf4d955223e5fcb1ca62810b37ed57", + "txHash": "0xbe1ff9cb949a53209b778708265740dfa2a08a93cfce4c897a53989a5d93f8c1" }, "L2Staking": { "address": "0x865365C425f3A593Ffe698D9c4E6707D14d51e08", @@ -1145,12 +1146,12 @@ "txHash": "0x326cf1f2849da4bb4d7e39f2783779e3c99fa48e4ee8ef004cfdd50c62e775df", "proxy": true, "implementation": { - "address": "0x6510B33cE246dd1F8A4BE1825F32A55995b38fcA", - "creationCodeHash": "0xdd9abafadeb64727a4c8b366c9af368f4a1a4113bde7acbe6b30387c7198ac7e", - "runtimeCodeHash": "0xbd37a4fd4850f58fadcf90e63c151927dd48f6fa9ed07843114f112acadc9138", - "txHash": "0xfbc3c6b153a7721d3cc8fac88ada18b98bb69ff1144762812e0617c5f7605fb9", + "address": "0xD07dFD514dc1b57020e6C1F49e05c48d0658C99f", + "creationCodeHash": "0x6a763345e5f166ea4e73ce9a116a49c9fc0833d9ea235a86fa5a997e91cf09e5", + "runtimeCodeHash": "0xb4c31859ac132241f04c802d4add70a94c7f2c6eb9dfd4bf224048d249dbc7bc", + "txHash": "0x68b34eda64287b84582c8f005c4e96162252d36c9c5c9b84332336a7c2e3d6d3", "libraries": { - "LibExponential": "0xf02277DA40b10e68E958131f36FbB9b59EE144C9" + "LibExponential": "0xd844116f6d79a280b117Bb6d9EBf4121D4e8B44b" } } }, @@ -1183,10 +1184,10 @@ "txHash": "0xb3764f4b576b46ee8dc6cbf680cad650b3ba80aa93dc6cf099862cfe8efc8a68", "proxy": true, "implementation": { - "address": "0x841B2a6055B816f8f2c7409b1234e8B73e8Cf1fE", - "creationCodeHash": "0x9d7257851678e3a0bd8ef74c219c314de490ebe91e6263129a3030d841dfc74b", - "runtimeCodeHash": "0xe490c3ae892d23d6ebed61a6081d70045ee6618f5196f25c28e6d7d66f798fee", - "txHash": "0xa8863f34d6e6d7a12d76c49e5f44aee9a6221ab30c755822e17c119d9e4f0d23" + "address": "0x887aC2f58D62Ac86d4E9aEc07c953991e3ca1bA3", + "creationCodeHash": "0xce4c47d94a33d69e03d607dd13a9ad1ed7fa730ef4a2308eb56ddd646ebaa0aa", + "runtimeCodeHash": "0x18d4a1659ccecede3d4d305ef1db4653d8f3dcbd4012f4e52200ae9f0c6c322c", + "txHash": "0x59d99afb9cefbb5c2275d9ac2d7230ac7f4a4cfb2440636408988a66075c032a" } }, "AllocationExchange": { diff --git a/packages/contracts/audits/OpenZeppelin/2024-02-subgraph-availability-manager-and-minimum-allocation-duration-removal.pdf b/packages/contracts/audits/OpenZeppelin/2024-02-subgraph-availability-manager-and-minimum-allocation-duration-removal.pdf new file mode 100644 index 000000000..d41a64e75 Binary files /dev/null and b/packages/contracts/audits/OpenZeppelin/2024-02-subgraph-availability-manager-and-minimum-allocation-duration-removal.pdf differ diff --git a/packages/contracts/cli/README.md b/packages/contracts/cli/README.md deleted file mode 100644 index 22feb9a90..000000000 --- a/packages/contracts/cli/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# CLI - -## Setup - -These are convenience commands for interacting with the contracts. - -The CLI expect a `.env` file with the following setup: - -``` -MNEMONIC= -ETHERSCAN_API_KEY= -INFURA_KEY= -ADDRESS_BOOK="addresses.json" -GRAPH_CONFIG="config/graph.mainnet.yml" -PROVIDER_URL="http://127.0.0.1:8545" -``` - -Also, run the following to create the proper typescript bindings for each contract: - -```sh -yarn build -``` - -## Usage - -Run the CLI with `./cli/cli.ts` from the project root folder. - -If will print a help with the available commands and parameters. - -## Organization - -The CLI is organized around commands and subcommands. These commands are defined in the `commands/` folder. - -Under the `commands/` there is one file per general command and a folder called `contracts` holding the commands for particular contract interactions. - -- `/cli` - - This folder is a CLI that allows for deploying contracts to ethereum networks. It uses yargs - - `/cli/cli.ts` - - This is the main entry point for the CLI. - - `/cli/commands/contracts` - - This has functions to call the contract functions directly to interact on chain. - - `/cli/commands/scenarios` - - This is where scenarios live. Scenarios are pre-planned interactions of many txs on chain. - They are useful for populating data in our contracts to see the subgraph, or to simulate - real world scenarios on chain - - There are also single files that provide a command for the CLI, which are: - - `deploy.ts` - helper to deploy a single contract. - - `migrate.ts` - helper to migrate all contracts for a new network on chain. - - `protocol.ts` - list, set or get any protocol parameter on any contract. - - `airdrop.ts` - distribute tokens to multiple addresses. - - `verify.ts` - verify a contract is on chain. - - `upgrade.ts` - helper to upgrade a proxy to use a new implementation. diff --git a/packages/contracts/cli/address-book.ts b/packages/contracts/cli/address-book.ts deleted file mode 100644 index 5c938fe2a..000000000 --- a/packages/contracts/cli/address-book.ts +++ /dev/null @@ -1,66 +0,0 @@ -import fs from 'fs' -import { constants } from 'ethers' - -const { AddressZero } = constants - -export type AddressBookEntry = { - address: string - constructorArgs?: Array - initArgs?: Array - creationCodeHash?: string - runtimeCodeHash?: string - txHash?: string - proxy?: boolean - implementation?: AddressBookEntry - libraries?: { [libraryName: string]: string } -} - -export type AddressBookJson = { - [chainId: string]: { - [contractName: string]: AddressBookEntry - } -} - -export interface AddressBook { - listEntries: () => Array - getEntry: (contractName: string) => AddressBookEntry - setEntry: (contractName: string, entry: AddressBookEntry) => void -} - -export const getAddressBook = (path: string, chainId: string): AddressBook => { - if (!path) throw new Error(`A path to the address book file is required.`) - if (!chainId) throw new Error(`A chainId is required.`) - - const addressBook = JSON.parse(fs.readFileSync(path, 'utf8') || '{}') as AddressBookJson - - if (!addressBook[chainId]) { - addressBook[chainId] = {} - } - - const listEntries = (): Array => { - return Object.keys(addressBook[chainId]) - } - - const getEntry = (contractName: string): AddressBookEntry => { - try { - return addressBook[chainId][contractName] - } catch (e) { - return { address: AddressZero } - } - } - - const setEntry = (contractName: string, entry: AddressBookEntry): void => { - addressBook[chainId][contractName] = entry - try { - fs.writeFileSync(path, JSON.stringify(addressBook, null, 2)) - } catch (e) { - console.log(`Error saving artifacts: ${e.message}`) - } - } - - return { - listEntries, - getEntry, - setEntry, - } -} diff --git a/packages/contracts/cli/arbitrum.ts b/packages/contracts/cli/arbitrum.ts deleted file mode 100644 index 727a19fa7..000000000 --- a/packages/contracts/cli/arbitrum.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { - L1ToL2MessageReader, - L1ToL2MessageStatus, - L1ToL2MessageWriter, - L1TransactionReceipt, - L2ToL1MessageReader, - L2ToL1MessageStatus, - L2ToL1MessageWriter, - L2TransactionReceipt, -} from '@arbitrum/sdk' -import { providers, Signer } from 'ethers' -import { Provider } from '@ethersproject/abstract-provider' - -// L1 -> L2 -export async function getL1ToL2MessageWriter( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, - signer: Signer, -): Promise { - return (await getL1ToL2Message( - txHashOrReceipt, - l1Provider, - l2Provider, - signer, - )) as L1ToL2MessageWriter -} - -export async function getL1ToL2MessageReader( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, -): Promise { - return await getL1ToL2Message(txHashOrReceipt, l1Provider, l2Provider) -} - -export async function getL1ToL2MessageStatus( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, -): Promise { - const message = await getL1ToL2Message(txHashOrReceipt, l1Provider, l2Provider) - return await message.status() -} - -async function getL1ToL2Message( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, - signer?: Signer, -): Promise { - const txReceipt = - typeof txHashOrReceipt === 'string' - ? await l1Provider.getTransactionReceipt(txHashOrReceipt) - : txHashOrReceipt - const l2SignerOrProvider = signer ? signer.connect(l2Provider) : l2Provider - const l1Receipt = new L1TransactionReceipt(txReceipt) - const l1ToL2Messages = await l1Receipt.getL1ToL2Messages(l2SignerOrProvider) - return l1ToL2Messages[0] -} - -// L2 -> L1 -export async function getL2ToL1MessageWriter( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, - signer: Signer, -): Promise { - return (await getL2ToL1Message( - txHashOrReceipt, - l1Provider, - l2Provider, - signer, - )) as L2ToL1MessageWriter -} - -export async function getL2ToL1MessageReader( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, -): Promise { - return await getL2ToL1Message(txHashOrReceipt, l1Provider, l2Provider) -} - -export async function getL2ToL1MessageStatus( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, -): Promise { - const message = await getL2ToL1Message(txHashOrReceipt, l1Provider, l2Provider) - return await message.status(l2Provider) -} - -async function getL2ToL1Message( - txHashOrReceipt: string | providers.TransactionReceipt, - l1Provider: Provider, - l2Provider: Provider, - signer?: Signer, -) { - const txReceipt = - typeof txHashOrReceipt === 'string' - ? await l2Provider.getTransactionReceipt(txHashOrReceipt) - : txHashOrReceipt - const l1SignerOrProvider = signer ? signer.connect(l1Provider) : l1Provider - const l2Receipt = new L2TransactionReceipt(txReceipt) - const l2ToL1Messages = await l2Receipt.getL2ToL1Messages(l1SignerOrProvider) - return l2ToL1Messages[0] -} diff --git a/packages/contracts/cli/artifacts.ts b/packages/contracts/cli/artifacts.ts deleted file mode 100644 index 35ddc7738..000000000 --- a/packages/contracts/cli/artifacts.ts +++ /dev/null @@ -1,23 +0,0 @@ -import path from 'path' -import { Artifacts } from 'hardhat/internal/artifacts' -import { LinkReferences } from 'hardhat/types' -import { utils } from 'ethers' - -type Abi = Array - -type Artifact = { - contractName: string - abi: Abi - bytecode: string - deployedBytecode: string - linkReferences?: LinkReferences - deployedLinkReferences?: LinkReferences -} - -const ARTIFACTS_PATH = path.resolve('build/contracts') - -const artifacts = new Artifacts(ARTIFACTS_PATH) - -export const loadArtifact = (name: string): Artifact => { - return artifacts.readArtifactSync(name) -} diff --git a/packages/contracts/cli/cli.ts b/packages/contracts/cli/cli.ts deleted file mode 100755 index ab2449679..000000000 --- a/packages/contracts/cli/cli.ts +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env ts-node -import * as dotenv from 'dotenv' -import yargs from 'yargs' - -import { deployCommand } from './commands/deploy' -import { migrateCommand } from './commands/migrate' -import { proxyCommand } from './commands/proxy' -import { protocolCommand } from './commands/protocol' -import { contractsCommand } from './commands/contracts' -import { airdropCommand } from './commands/airdrop' -import { bridgeCommand } from './commands/bridge' - -import { cliOpts } from './defaults' - -dotenv.config() - -yargs - .parserConfiguration({ - 'short-option-groups': true, - 'camel-case-expansion': true, - 'dot-notation': true, - 'parse-numbers': false, - 'parse-positional-numbers': false, - 'boolean-negation': true, - }) - .env(true) - .option('a', cliOpts.addressBook) - .option('m', cliOpts.mnemonic) - .option('p', cliOpts.providerUrl) - .option('n', cliOpts.accountNumber) - .option('s', cliOpts.skipConfirmation) - .option('r', cliOpts.arbitrumAddressBook) - .command(deployCommand) - .command(migrateCommand) - .command(proxyCommand) - .command(protocolCommand) - .command(contractsCommand) - .command(airdropCommand) - .command(bridgeCommand) - .demandCommand(1, 'Choose a command from the above list') - .help().argv diff --git a/packages/contracts/cli/commands/airdrop.ts b/packages/contracts/cli/commands/airdrop.ts deleted file mode 100644 index 00b842dfe..000000000 --- a/packages/contracts/cli/commands/airdrop.ts +++ /dev/null @@ -1,282 +0,0 @@ -import fs from 'fs' -import PQueue from 'p-queue' -import yargs, { Argv } from 'yargs' -import { parseGRT, formatGRT } from '@graphprotocol/common-ts' - -import { utils, BigNumber, Contract } from 'ethers' -import { NonceManager } from '@ethersproject/experimental' - -import { logger } from '../logging' -import { sendTransaction } from '../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../env' -import { confirm } from '../helpers' - -const { getAddress } = utils - -const DISPERSE_CONTRACT_ADDRESS = { - 1: '0xD152f549545093347A162Dce210e7293f1452150', - 4: '0xD152f549545093347A162Dce210e7293f1452150', - 1337: '0xD152f549545093347A162Dce210e7293f1452150', -} - -const DISPERSE_CONTRACT_ABI = [ - { - constant: false, - inputs: [ - { name: 'token', type: 'address' }, - { name: 'recipients', type: 'address[]' }, - { name: 'values', type: 'uint256[]' }, - ], - name: 'disperseTokenSimple', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', - }, - { - constant: false, - inputs: [ - { name: 'token', type: 'address' }, - { name: 'recipients', type: 'address[]' }, - { name: 'values', type: 'uint256[]' }, - ], - name: 'disperseToken', - outputs: [], - payable: false, - stateMutability: 'nonpayable', - type: 'function', - }, - { - constant: false, - inputs: [ - { name: 'recipients', type: 'address[]' }, - { name: 'values', type: 'uint256[]' }, - ], - name: 'disperseEther', - outputs: [], - payable: true, - stateMutability: 'payable', - type: 'function', - }, -] - -interface AirdropRecipient { - address: string - amount: BigNumber - txHash?: string -} - -const getDisperseContract = (chainID: number, provider) => { - return new Contract(DISPERSE_CONTRACT_ADDRESS[chainID], DISPERSE_CONTRACT_ABI, provider) -} - -const loadRecipients = (path: string): Array => { - const data = fs.readFileSync(path, 'utf8') - const lines = data.split('\n').map((e) => e.trim()) - - const results: Array = [] - for (const line of lines) { - const [address, amount, txHash] = line.split(',').map((e) => e.trim()) - - // Skip any empty value - if (!address) continue - - // Test for zero amount and fail - const weiAmount = parseGRT(amount) - if (weiAmount.eq(0)) { - logger.crit(`Error loading address "${address}" - amount is zero`) - process.exit(0) - } - - // Validate address format - try { - getAddress(address) - } catch (err) { - // Full stop on error - logger.crit(`Error loading address "${address}" please review the input file`) - process.exit(1) - } - results.push({ address, amount: weiAmount, txHash }) - } - return results -} - -const sumTotalAmount = (recipients: Array): BigNumber => { - let total = BigNumber.from(0) - for (const recipient of recipients) { - total = total.add(recipient.amount) - } - return total -} - -const saveResumeList = (path: string, txHash: string, recipients: Array) => { - for (const recipient of recipients) { - const line = [recipient.address, formatGRT(recipient.amount), txHash].join(',') + '\n' - fs.writeFileSync(path, line, { - flag: 'a+', - }) - } -} - -const loadResumeList = (path: string): Array => { - try { - return loadRecipients(path) - } catch (err) { - if (err.code === 'ENOENT') { - logger.warn('No existing resumefile, one will be created') - return [] - } else { - throw err - } - } -} - -const createBatches = ( - items: Array, - batchSize = 10, -): Array> => { - const remainingItems = Object.assign([], items) - const batches = [] - while (remainingItems.length > 0) { - const batchItems = remainingItems.splice(0, batchSize) - batches.push(batchItems) - if (batchItems.length < batchSize) { - break - } - } - return batches -} - -export const airdrop = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const graphToken = cli.contracts.GraphToken - const skipConfirmation = cliArgs.skipConfirmation - - // Load data - const resumeList = loadResumeList(cliArgs.resumefile).map((r) => r.address) - const recipients = loadRecipients(cliArgs.recipients).filter( - (r) => !resumeList.includes(r.address), - ) - const totalAmount = sumTotalAmount(recipients) - - // Summary - logger.info(`# Batch Size: ${cliArgs.batchSize}`) - logger.info(`# Concurrency: ${cliArgs.concurrency}`) - logger.info(`> Token: ${graphToken.address}`) - logger.info(`> Distributing: ${formatGRT(totalAmount)} tokens (${totalAmount} wei)`) - logger.info(`> Resumelist: ${resumeList.length} addresses`) - logger.info(`> Recipients: ${recipients.length} addresses\n`) - - // Validity check - if (totalAmount.eq(0)) { - logger.crit('Cannot proceed with a distribution of zero tokens') - process.exit(1) - } - - // Load airdrop contract - const disperseContract = getDisperseContract(cli.chainId, cli.wallet.provider) - if (!disperseContract.address) { - logger.crit('Disperse contract not found. Please review your network settings.') - process.exit(1) - } - - // Confirmation - const sure = await confirm( - 'Are you sure you want to proceed with the distribution?', - skipConfirmation, - ) - if (!sure) return - - // Approve - logger.info('## Token approval') - const allowance = ( - await graphToken.functions['allowance'](cli.wallet.address, disperseContract.address) - )[0] - if (allowance.gte(totalAmount)) { - logger.info('Already have enough allowance, no need to approve more...') - } else { - logger.info( - `Approve disperse:${disperseContract.address} for ${formatGRT( - totalAmount, - )} tokens (${totalAmount} wei)`, - ) - await sendTransaction(cli.wallet, graphToken, 'approve', [ - disperseContract.address, - totalAmount, - ]) - } - - // Distribute - logger.info('## Distribution') - const queue = new PQueue({ concurrency: cliArgs.concurrency }) - const recipientsBatches = createBatches(recipients, cliArgs.batchSize) - const nonceManager = new NonceManager(cli.wallet) // Use NonceManager to send concurrent txs - - let batchNum = 0 - let recipientsCount = 0 - for (const batch of recipientsBatches) { - queue.add(async () => { - const addressList = batch.map((r) => r.address) - const amountList = batch.map((r) => r.amount) - - recipientsCount += addressList.length - batchNum++ - logger.info(`Sending batch #${batchNum} : ${recipientsCount}/${recipients.length}`) - for (const recipient of batch) { - logger.info( - ` > Transferring ${recipient.address} => ${formatGRT(recipient.amount)} (${ - recipient.amount - } wei)`, - ) - } - try { - const receipt = await sendTransaction(nonceManager, disperseContract, 'disperseToken', [ - graphToken.address, - addressList, - amountList, - ]) - saveResumeList(cliArgs.resumefile, receipt.transactionHash, batch) - } catch (err) { - logger.error(`Failed to send #${batchNum}`, err) - } - }) - } - await queue.onIdle() -} - -export const airdropCommand = { - command: 'airdrop', - describe: 'Airdrop tokens', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('recipients', { - description: 'Path to the file with information for the airdrop. CSV file address,amount', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('resumefile', { - description: - 'Path to the file used for resuming. Stores results with CSV format: address,amount,txHash', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('batch-size', { - description: 'Number of addresses to send in a single transaction', - type: 'number', - requiresArg: true, - demandOption: true, - default: 100, - }) - .option('concurrency', { - description: 'Number of simultaneous transfers', - type: 'number', - requiresArg: true, - demandOption: false, - default: 1, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return airdrop(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/bridge/index.ts b/packages/contracts/cli/commands/bridge/index.ts deleted file mode 100644 index fcdf1bcc1..000000000 --- a/packages/contracts/cli/commands/bridge/index.ts +++ /dev/null @@ -1,22 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { redeemSendToL2Command, sendToL2Command } from './to-l2' -import { startSendToL1Command, finishSendToL1Command, waitFinishSendToL1Command } from './to-l1' -import { cliOpts } from '../../defaults' - -export const bridgeCommand = { - command: 'bridge', - describe: 'Graph token bridge actions.', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('-l', cliOpts.l2ProviderUrl) - .command(sendToL2Command) - .command(redeemSendToL2Command) - .command(startSendToL1Command) - .command(finishSendToL1Command) - .command(waitFinishSendToL1Command) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/bridge/to-l1.ts b/packages/contracts/cli/commands/bridge/to-l1.ts deleted file mode 100644 index ede94a2ee..000000000 --- a/packages/contracts/cli/commands/bridge/to-l1.ts +++ /dev/null @@ -1,277 +0,0 @@ -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { logger } from '../../logging' -import { getAddressBook } from '../../address-book' -import { getProvider, sendTransaction, toGRT } from '../../network' -import { chainIdIsL2 } from '../../cross-chain' -import { loadAddressBookContract } from '../../contracts' -import { L2TransactionReceipt, L2ToL1MessageStatus, L2ToL1MessageWriter } from '@arbitrum/sdk' -import { L2GraphTokenGateway } from '../../../build/types/L2GraphTokenGateway' -import { BigNumber } from 'ethers' -import { JsonRpcProvider } from '@ethersproject/providers' -import { providers } from 'ethers' -import { L2GraphToken } from '../../../build/types/L2GraphToken' -import { getL2ToL1MessageReader, getL2ToL1MessageWriter } from '../../arbitrum' -import { getContractAt } from '../../network' -import { Argv } from 'yargs' - -const LEGACY_L2_GRT_ADDRESS = '0x23A941036Ae778Ac51Ab04CEa08Ed6e2FE103614' -const LEGACY_L2_GATEWAY_ADDRESS = '0x09e9222e96e7b4ae2a407b98d48e330053351eee' - -const FOURTEEN_DAYS_IN_SECONDS = 24 * 3600 * 14 - -const BLOCK_SEARCH_THRESHOLD = 6 * 3600 -const searchForArbBlockByTimestamp = async ( - l2Provider: JsonRpcProvider, - timestamp: number, -): Promise => { - let step = 131072 - let block = await l2Provider.getBlock('latest') - while (block.timestamp > timestamp) { - while (block.number - step < 0) { - step = Math.round(step / 2) - } - block = await l2Provider.getBlock(block.number - step) - } - while (step > 1 && Math.abs(block.timestamp - timestamp) > BLOCK_SEARCH_THRESHOLD) { - step = Math.round(step / 2) - if (block.timestamp - timestamp > 0) { - block = await l2Provider.getBlock(block.number - step) - } else { - block = await l2Provider.getBlock(block.number + step) - } - } - return block.number -} - -const wait = (ms: number): Promise => { - return new Promise((res) => setTimeout(res, ms)) -} - -const waitUntilOutboxEntryCreatedWithCb = async ( - msg: L2ToL1MessageWriter, - provider: providers.Provider, - retryDelay: number, - callback: () => void, -) => { - let done = false - while (!done) { - const status = await msg.status(provider) - if (status == L2ToL1MessageStatus.CONFIRMED || status == L2ToL1MessageStatus.EXECUTED) { - done = true - } else { - callback() - await wait(retryDelay) - } - } -} - -export const startSendToL1 = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - logger.info(`>>> Sending tokens to L1 <<<\n`) - const l2Provider = getProvider(cliArgs.l2ProviderUrl) - const l2ChainId = (await l2Provider.getNetwork()).chainId - - if (chainIdIsL2(cli.chainId) || !chainIdIsL2(l2ChainId)) { - throw new Error( - 'Please use an L1 provider in --provider-url, and an L2 provider in --l2-provider-url', - ) - } - - const l1GRT = cli.contracts['GraphToken'] - const l1GRTAddress = l1GRT.address - const amount = toGRT(cliArgs.amount) - const recipient = cliArgs.recipient ? cliArgs.recipient : cli.wallet.address - const l2Wallet = cli.wallet.connect(l2Provider) - const l2AddressBook = getAddressBook(cliArgs.addressBook, l2ChainId.toString()) - - let gateway: L2GraphTokenGateway - let l2GRT: L2GraphToken - if (cliArgs.legacyToken) { - gateway = getContractAt( - 'L2GraphTokenGateway', - LEGACY_L2_GATEWAY_ADDRESS, - l2Wallet, - ) as L2GraphTokenGateway - l2GRT = getContractAt('L2GraphToken', LEGACY_L2_GRT_ADDRESS, l2Wallet) as L2GraphToken - } else { - gateway = loadAddressBookContract( - 'L2GraphTokenGateway', - l2AddressBook, - l2Wallet, - ) as L2GraphTokenGateway - l2GRT = loadAddressBookContract('L2GraphToken', l2AddressBook, l2Wallet) as L2GraphToken - } - - logger.info(`Will send ${cliArgs.amount} GRT to ${recipient}`) - logger.info(`Using L2 gateway ${gateway.address}`) - - const senderBalance = await l2GRT.balanceOf(cli.wallet.address) - if (senderBalance.lt(amount)) { - throw new Error('Sender balance is insufficient for the transfer') - } - - const params = [l1GRTAddress, recipient, amount, '0x'] - if (!cliArgs.legacyToken) { - logger.info('Approving token transfer') - await sendTransaction(l2Wallet, l2GRT, 'approve', [gateway.address, amount]) - } - logger.info('Sending outbound transfer transaction') - const receipt = await sendTransaction( - l2Wallet, - gateway, - 'outboundTransfer(address,address,uint256,bytes)', - params, - ) - - const l2ToL1Message = await getL2ToL1MessageReader(receipt, cli.wallet.provider, l2Provider) - const l2Receipt = new L2TransactionReceipt(receipt) - - const ethBlockNum = await l2ToL1Message.getFirstExecutableBlock(l2Provider) - if (ethBlockNum === null) { - logger.info(`L2 to L1 message can or already has been executed. If not finalized call`) - } else { - logger.info(`The transaction generated an L2 to L1 message in outbox with eth block number:`) - logger.info(ethBlockNum.toString()) - logger.info( - `After the dispute period is finalized (in ~1 week), you can finalize this by calling`, - ) - } - logger.info(`finish-send-to-l1 with the following txhash:`) - logger.info(l2Receipt.transactionHash) -} - -export const finishSendToL1 = async ( - cli: CLIEnvironment, - cliArgs: CLIArgs, - wait: boolean, -): Promise => { - logger.info(`>>> Finishing transaction sending tokens to L1 <<<\n`) - const l2Provider = getProvider(cliArgs.l2ProviderUrl) - const l2ChainId = (await l2Provider.getNetwork()).chainId - - if (chainIdIsL2(cli.chainId) || !chainIdIsL2(l2ChainId)) { - throw new Error( - 'Please use an L1 provider in --provider-url, and an L2 provider in --l2-provider-url', - ) - } - - const l2AddressBook = getAddressBook(cliArgs.addressBook, l2ChainId.toString()) - - let gateway: L2GraphTokenGateway - if (cliArgs.legacyToken) { - gateway = getContractAt( - 'L2GraphTokenGateway', - LEGACY_L2_GATEWAY_ADDRESS, - l2Provider, - ) as L2GraphTokenGateway - } else { - gateway = loadAddressBookContract( - 'L2GraphTokenGateway', - l2AddressBook, - l2Provider, - ) as L2GraphTokenGateway - } - let txHash: string - if (cliArgs.txHash) { - txHash = cliArgs.txHash - } else { - logger.info( - `Looking for withdrawals initiated by ${cli.wallet.address} in roughly the last 14 days`, - ) - const fromBlock = await searchForArbBlockByTimestamp( - l2Provider, - Math.round(Date.now() / 1000) - FOURTEEN_DAYS_IN_SECONDS, - ) - const filt = gateway.filters.WithdrawalInitiated(null, cli.wallet.address) - const allEvents = await gateway.queryFilter(filt, BigNumber.from(fromBlock).toHexString()) - if (allEvents.length == 0) { - throw new Error('No withdrawals found') - } - txHash = allEvents[allEvents.length - 1].transactionHash - } - logger.info(`Getting receipt from transaction ${txHash}`) - const l2ToL1Message = await getL2ToL1MessageWriter( - txHash, - cli.wallet.provider, - l2Provider, - cli.wallet, - ) - - if (wait) { - const retryDelayMs = cliArgs.retryDelaySeconds ? cliArgs.retryDelaySeconds * 1000 : 60000 - logger.info('Waiting for outbox entry to be created, this can take a full week...') - await waitUntilOutboxEntryCreatedWithCb(l2ToL1Message, l2Provider, retryDelayMs, () => { - logger.info('Still waiting...') - }) - } else { - const status = await l2ToL1Message.status(l2Provider) - if (status == L2ToL1MessageStatus.EXECUTED) { - throw new Error('Message already executed!') - } else if (status != L2ToL1MessageStatus.CONFIRMED) { - throw new Error( - `Transaction is not confirmed, status is ${status} when it should be ${L2ToL1MessageStatus.CONFIRMED}. Has the dispute period passed?`, - ) - } - } - - logger.info('Executing outbox transaction') - const tx = await l2ToL1Message.execute(l2Provider) - const outboxExecuteReceipt = await tx.wait() - logger.info('Transaction succeeded! tx hash:') - logger.info(outboxExecuteReceipt.transactionHash) -} - -export const startSendToL1Command = { - command: 'start-send-to-l1 [recipient]', - describe: 'Start an L2-to-L1 Graph Token transaction', - builder: (yargs: Argv): Argv => { - return yargs - .option('legacy-token', { - type: 'boolean', - default: false, - description: 'Use the legacy GRT token', - }) - .positional('amount', { - type: 'string', - description: 'The amount of tokens to send', - }) - .positional('recipient', { - type: 'string', - description: 'The recipient of the tokens on L1. Same as the L2 sender if empty.', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return startSendToL1(await loadEnv(argv), argv) - }, -} - -export const finishSendToL1Command = { - command: 'finish-send-to-l1 [txHash]', - describe: - 'Finish an L2-to-L1 Graph Token transaction. L2 dispute period must have completed. ' + - 'If txHash is not specified, the last withdrawal from the main account in the past 14 days will be redeemed.', - builder: (yargs: Argv): Argv => { - return yargs - .option('legacy-token', { - type: 'boolean', - default: false, - description: 'Use the legacy GRT token', - }) - .positional('txHash', { - type: 'string', - description: 'The transaction hash of the withdrawal on L2', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return finishSendToL1(await loadEnv(argv), argv, false) - }, -} - -export const waitFinishSendToL1Command = { - command: 'wait-finish-send-to-l1 [txHash] [retryDelaySeconds]', - describe: - "Wait for an L2-to-L1 Graph Token transaction's dispute period to complete (which takes about a week), and then finalize it. " + - 'If txHash is not specified, the last withdrawal from the main account in the past 14 days will be redeemed.', - handler: async (argv: CLIArgs): Promise => { - return finishSendToL1(await loadEnv(argv), argv, true) - }, -} diff --git a/packages/contracts/cli/commands/bridge/to-l2.ts b/packages/contracts/cli/commands/bridge/to-l2.ts deleted file mode 100644 index b7d64795a..000000000 --- a/packages/contracts/cli/commands/bridge/to-l2.ts +++ /dev/null @@ -1,193 +0,0 @@ -import { Argv } from 'yargs' -import { utils } from 'ethers' -import { L1TransactionReceipt, L1ToL2MessageStatus, L1ToL2MessageWriter } from '@arbitrum/sdk' - -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { logger } from '../../logging' -import { getProvider, sendTransaction, toGRT, ensureAllowance, toBN } from '../../network' -import { chainIdIsL2, estimateRetryableTxGas } from '../../cross-chain' -import { getL1ToL2MessageWriter } from '../../arbitrum' - -const logAutoRedeemReason = (autoRedeemRec) => { - if (autoRedeemRec == null) { - logger.info(`Auto redeem was not attempted.`) - return - } - logger.info(`Auto redeem reverted.`) -} - -const checkAndRedeemMessage = async (l1ToL2Message: L1ToL2MessageWriter) => { - logger.info(`Waiting for status of ${l1ToL2Message.retryableCreationId}`) - const res = await l1ToL2Message.waitForStatus() - logger.info('Getting auto redeem attempt') - const autoRedeemRec = await l1ToL2Message.getAutoRedeemAttempt() - const l2TxReceipt = res.status === L1ToL2MessageStatus.REDEEMED ? res.l2TxReceipt : autoRedeemRec - let l2TxHash = l2TxReceipt ? l2TxReceipt.transactionHash : 'null' - if (res.status === L1ToL2MessageStatus.FUNDS_DEPOSITED_ON_L2) { - /** Message wasn't auto-redeemed! */ - logger.warn('Funds were deposited on L2 but the retryable ticket was not redeemed') - logAutoRedeemReason(autoRedeemRec) - logger.info('Attempting to redeem...') - await l1ToL2Message.redeem(process.env.CI ? { gasLimit: 2_000_000 } : {}) - const redeemAttempt = await l1ToL2Message.getSuccessfulRedeem() - if (redeemAttempt.status == L1ToL2MessageStatus.REDEEMED) { - l2TxHash = redeemAttempt.l2TxReceipt ? redeemAttempt.l2TxReceipt.transactionHash : 'null' - } else { - throw new Error(`Unexpected L1ToL2MessageStatus after redeem attempt: ${res.status}`) - } - } else if (res.status != L1ToL2MessageStatus.REDEEMED) { - throw new Error(`Unexpected L1ToL2MessageStatus ${res.status}`) - } - logger.info(`Transfer successful: ${l2TxHash}`) -} - -const ifNotNullToBN = (val: string | null) => (val == null ? val : toBN(val)) - -export const sendToL2 = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - logger.info(`>>> Sending tokens to L2 <<<\n`) - - // parse provider - const l1Provider = cli.wallet.provider - // TODO: fix this hack for usage with hardhat - const l2Provider = cliArgs.l2Provider ? cliArgs.l2Provider : getProvider(cliArgs.l2ProviderUrl) - const l1ChainId = cli.chainId - const l2ChainId = (await l2Provider.getNetwork()).chainId - if (chainIdIsL2(l1ChainId) || !chainIdIsL2(l2ChainId)) { - throw new Error( - 'Please use an L1 provider in --provider-url, and an L2 provider in --l2-provider-url', - ) - } - - // parse params - const { L1GraphTokenGateway: l1Gateway, GraphToken: l1GRT } = cli.contracts - const amount = toGRT(cliArgs.amount) - const recipient = cliArgs.recipient ?? cli.wallet.address - const l1GatewayAddress = l1Gateway.address - const l2GatewayAddress = await l1Gateway.l2Counterpart() - const calldata = cliArgs.calldata ?? '0x' - - // transport tokens - logger.info(`Will send ${cliArgs.amount} GRT to ${recipient}`) - logger.info(`Using L1 gateway ${l1GatewayAddress} and L2 gateway ${l2GatewayAddress}`) - await ensureAllowance(cli.wallet, l1GatewayAddress, l1GRT, amount) - - // estimate L2 ticket - // See https://github.com/OffchainLabs/arbitrum/blob/master/packages/arb-ts/src/lib/bridge.ts - const depositCalldata = await l1Gateway.getOutboundCalldata( - l1GRT.address, - cli.wallet.address, - recipient, - amount, - calldata, - ) - const { maxGas, gasPriceBid, maxSubmissionCost } = await estimateRetryableTxGas( - l1Provider, - l2Provider, - l1GatewayAddress, - l2GatewayAddress, - depositCalldata, - { - maxGas: cliArgs.maxGas, - gasPriceBid: cliArgs.gasPriceBid, - maxSubmissionCost: cliArgs.maxSubmissionCost, - }, - ) - const ethValue = maxSubmissionCost.add(gasPriceBid.mul(maxGas)) - logger.info( - `Using maxGas:${maxGas}, gasPriceBid:${gasPriceBid}, maxSubmissionCost:${maxSubmissionCost} = tx value: ${ethValue}`, - ) - - // build transaction - logger.info('Sending outbound transfer transaction') - const txData = utils.defaultAbiCoder.encode(['uint256', 'bytes'], [maxSubmissionCost, calldata]) - const txParams = [l1GRT.address, recipient, amount, maxGas, gasPriceBid, txData] - const txReceipt = await sendTransaction(cli.wallet, l1Gateway, 'outboundTransfer', txParams, { - value: ethValue, - }) - - // get l2 ticket status - if (txReceipt.status == 1) { - logger.info('Waiting for message to propagate to L2...') - const l1ToL2Message = await getL1ToL2MessageWriter( - txReceipt, - cli.wallet.provider, - l2Provider, - cli.wallet, - ) - try { - await checkAndRedeemMessage(l1ToL2Message) - } catch (e) { - logger.error('Auto redeem failed') - logger.error(e) - logger.error('You can re-attempt using redeem-send-to-l2 with the following txHash:') - logger.error(txReceipt.transactionHash) - } - } -} - -export const redeemSendToL2 = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - logger.info(`>>> Redeeming pending tokens on L2 <<<\n`) - const l2Provider = getProvider(cliArgs.l2ProviderUrl) - const l2ChainId = (await l2Provider.getNetwork()).chainId - - if (chainIdIsL2(cli.chainId) || !chainIdIsL2(l2ChainId)) { - throw new Error( - 'Please use an L1 provider in --provider-url, and an L2 provider in --l2-provider-url', - ) - } - const l1Provider = cli.wallet.provider - - const receipt = await l1Provider.getTransactionReceipt(cliArgs.txHash) - const l1Receipt = new L1TransactionReceipt(receipt) - const l1ToL2Messages = await l1Receipt.getL1ToL2Messages(cli.wallet.connect(l2Provider)) - const l1ToL2Message = l1ToL2Messages[0] - - logger.info('Checking message status in L2...') - await checkAndRedeemMessage(l1ToL2Message) -} - -export const sendToL2Command = { - command: 'send-to-l2 [recipient] [calldata]', - describe: 'Perform an L1-to-L2 Graph Token transaction', - builder: (yargs: Argv): Argv => { - return yargs - .option('max-gas', { - description: 'Max gas for the L2 redemption attempt', - requiresArg: true, - type: 'string', - }) - .option('gas-price-bid', { - description: 'Gas price for the L2 redemption attempt', - requiresArg: true, - type: 'string', - }) - .option('max-submission-cost', { - description: 'Max submission cost for the retryable ticket', - requiresArg: true, - type: 'string', - }) - .positional('amount', { description: 'Amount to send (will be converted to wei)' }) - .positional('recipient', { - description: 'Receiving address in L2. Same to L1 address if empty', - }) - .positional('calldata', { - description: 'Calldata to pass to the recipient. Must be allowlisted in the bridge', - }) - .coerce({ - maxGas: ifNotNullToBN, - gasPriceBid: ifNotNullToBN, - maxSubmissionCost: ifNotNullToBN, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return sendToL2(await loadEnv(argv), argv) - }, -} - -export const redeemSendToL2Command = { - command: 'redeem-send-to-l2 ', - describe: 'Finish an L1-to-L2 Graph Token transaction if it failed to auto-redeem', - handler: async (argv: CLIArgs): Promise => { - return redeemSendToL2(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/contracts/any.ts b/packages/contracts/cli/commands/contracts/any.ts deleted file mode 100644 index 647f71c87..000000000 --- a/packages/contracts/cli/commands/contracts/any.ts +++ /dev/null @@ -1,59 +0,0 @@ -import yargs, { Argv } from 'yargs' -import { ContractFunction } from 'ethers' - -import { logger } from '../../logging' -import { getContractAt, sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' - -export const any = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const contract = cliArgs.contract - const func = cliArgs.func - const addressEntry = cli.addressBook.getEntry(contract) - const params = cliArgs.params ? cliArgs.params.toString().split(',') : [] - const attachedContract = getContractAt(contract, addressEntry.address).connect(cli.wallet) - - if (cliArgs.type == 'get') { - logger.info(`Getting ${func}...`) - const contractFn: ContractFunction = attachedContract.functions[func] - const value = await contractFn(...params) - logger.info(`${func} = ${value}`) - } else if (cliArgs.type == 'set') { - logger.info(`Setting ${func}...`) - await sendTransaction(cli.wallet, attachedContract, func, params) - } -} - -export const anyCommand = { - command: 'any', - describe: 'Call a getter or a setter, on any contract', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('type', { - description: 'Choose get or set', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('contract', { - description: 'Name of contract, case sensitive', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('func', { - description: 'Name of function', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('params', { - description: 'All parameters, comma separated', - type: 'string', - requiresArg: true, - demandOption: false, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return any(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/contracts/curation.ts b/packages/contracts/cli/commands/contracts/curation.ts deleted file mode 100644 index 2c5abe7c6..000000000 --- a/packages/contracts/cli/commands/contracts/curation.ts +++ /dev/null @@ -1,86 +0,0 @@ -import yargs, { Argv } from 'yargs' -import { parseGRT } from '@graphprotocol/common-ts' - -import { logger } from '../../logging' -import { sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' - -export const mint = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphID = cliArgs.subgraphID - const amount = parseGRT(cliArgs.amount) - - const curation = cli.contracts.Curation - const graphToken = cli.contracts.GraphToken - - logger.info('First calling approve() to ensure curation contract can call transferFrom()...') - await sendTransaction(cli.wallet, graphToken, 'approve', [curation.address, amount]) - logger.info(`Signaling on ${subgraphID} with ${cliArgs.amount} tokens...`) - await sendTransaction(cli.wallet, curation, 'mint', [subgraphID, amount, 0], { - gasLimit: 2000000, - }) -} -export const burn = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphID = cliArgs.subgraphID - const amount = parseGRT(cliArgs.amount) - const curation = cli.contracts.Curation - - logger.info(`Burning signal on ${subgraphID} with ${cliArgs.amount} tokens...`) - await sendTransaction(cli.wallet, curation, 'burn', [subgraphID, amount, 0]) -} - -export const curationCommand = { - command: 'curation', - describe: 'Curation contract calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'mint', - describe: 'Mint signal for a subgraph deployment', - builder: (yargs: Argv) => { - return yargs - .option('s', { - alias: 'subgraphID', - description: 'The subgraph deployment ID being curated on', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of tokens being signaled. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return mint(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'burn', - describe: 'Burn signal of a subgraph deployment', - builder: (yargs: Argv) => { - return yargs - .option('s', { - alias: 'subgraphID', - description: 'The subgraph deployment ID being curated on', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of shares being redeemed. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return burn(await loadEnv(argv), argv) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/disputeManager.ts b/packages/contracts/cli/commands/contracts/disputeManager.ts deleted file mode 100644 index 88d0abce1..000000000 --- a/packages/contracts/cli/commands/contracts/disputeManager.ts +++ /dev/null @@ -1,247 +0,0 @@ -import yargs, { Argv } from 'yargs' -import { constants, utils, Wallet } from 'ethers' -import { createAttestation, Attestation, Receipt } from '@graphprotocol/common-ts' - -import { logger } from '../../logging' -import { sendTransaction, getProvider, toGRT, randomHexBytes } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { getChainID } from '../../network' - -const { HashZero } = constants -const { defaultAbiCoder: abi, arrayify, concat, hexlify } = utils - -interface ChannelKey { - privKey: string - pubKey: string - address: string -} - -async function buildAttestation(receipt: Receipt, signer: string, disputeManagerAddress: string) { - const attestation = await createAttestation( - signer, - getChainID(), - disputeManagerAddress, - receipt, - '0', - ) - return attestation -} - -export const deriveChannelKey = (): ChannelKey => { - const w = Wallet.createRandom() - return { privKey: w.privateKey, pubKey: w.publicKey, address: utils.computeAddress(w.publicKey) } -} - -function encodeAttestation(attestation: Attestation): string { - const data = arrayify( - abi.encode( - ['bytes32', 'bytes32', 'bytes32'], - [attestation.requestCID, attestation.responseCID, attestation.subgraphDeploymentID], - ), - ) - const sig = concat([ - arrayify(hexlify(attestation.v)), - arrayify(attestation.r), - arrayify(attestation.s), - ]) - return hexlify(concat([data, sig])) -} - -async function setupIndexer( - cli: CLIEnvironment, - cliArgs: CLIArgs, - indexerChannelKey: ChannelKey, - receipt: Receipt, - accountIndex: number, -) { - const indexer = Wallet.fromMnemonic(cliArgs.mnemonic, `m/44'/60'/0'/0/${accountIndex}`).connect( - getProvider(cliArgs.providerUrl), - ) - - const grt = cli.contracts.GraphToken - const staking = cli.contracts.Staking - - const indexerTokens = toGRT('100000') - const indexerAllocatedTokens = toGRT('10000') - const metadata = HashZero - - logger.info('Transferring tokens to the indexer...') - await sendTransaction(cli.wallet, grt, 'transfer', [indexer.address, indexerTokens]) - logger.info('Approving the staking address to pull tokens...') - await sendTransaction(cli.wallet, grt, 'approve', [staking.address, indexerTokens]) - logger.info('Staking...') - await sendTransaction(cli.wallet, staking, 'stake', [indexerTokens]) - logger.info('Allocating...') - await sendTransaction(cli.wallet, staking, 'allocate', [ - receipt.subgraphDeploymentID, - indexerAllocatedTokens, - indexerChannelKey.address, - metadata, - ]) -} - -// This just creates any query dispute conflict to test the subgraph, no real data is sent -export const createTestQueryDisputeConflict = async ( - cli: CLIEnvironment, - cliArgs: CLIArgs, -): Promise => { - // Derive some channel keys for each indexer used to sign attestations - const indexer1ChannelKey = deriveChannelKey() - const indexer2ChannelKey = deriveChannelKey() - - // Create an attesation receipt for the dispute - const receipt: Receipt = { - requestCID: randomHexBytes(), - responseCID: randomHexBytes(), - subgraphDeploymentID: randomHexBytes(), - } - - const receipt1 = receipt - const receipt2 = { ...receipt1, responseCID: randomHexBytes() } - - await setupIndexer(cli, cliArgs, indexer1ChannelKey, receipt1, 1) - await setupIndexer(cli, cliArgs, indexer2ChannelKey, receipt2, 2) - - const disputeManager = cli.contracts.DisputeManager - const disputeManagerAddr = disputeManager.address - - const attestation1 = await buildAttestation( - receipt1, - indexer1ChannelKey.privKey, - disputeManagerAddr, - ) - const attestation2 = await buildAttestation( - receipt2, - indexer2ChannelKey.privKey, - disputeManagerAddr, - ) - - logger.info(`Creating conflicting attestations...`) - await sendTransaction(cli.wallet, disputeManager, 'createQueryDisputeConflict', [ - encodeAttestation(attestation1), - encodeAttestation(attestation2), - ]) -} - -// This just creates any indexing dispute to test the subgraph, no real data is sent -export const createTestIndexingDispute = async ( - cli: CLIEnvironment, - cliArgs: CLIArgs, -): Promise => { - // Derive some channel keys for each indexer used to sign attestations - const indexerChannelKey = deriveChannelKey() - - // Create an attesation receipt for the dispute - const receipt: Receipt = { - requestCID: randomHexBytes(), - responseCID: randomHexBytes(), - subgraphDeploymentID: randomHexBytes(), - } - - await setupIndexer(cli, cliArgs, indexerChannelKey, receipt, 0) - - // min deposit is 100 GRT, so we do 1000 for safe measure - const deposit = toGRT('1000') - const disputeManager = cli.contracts.DisputeManager - const grt = cli.contracts.GraphToken - - logger.info('Approving the dispute address to pull tokens...') - await sendTransaction(cli.wallet, grt, 'approve', [disputeManager.address, deposit]) - - logger.info(`Creating indexing dispute...`) - await sendTransaction(cli.wallet, disputeManager, 'createIndexingDispute', [ - indexerChannelKey.address, - deposit, - ]) -} - -export const accept = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const disputeManager = cli.contracts.DisputeManager - const disputeID = cliArgs.disputeID - logger.info(`Accepting...`) - await sendTransaction(cli.wallet, disputeManager, 'acceptDispute', ...[disputeID]) -} - -export const reject = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const disputeManager = cli.contracts.DisputeManager - const disputeID = cliArgs.disputeID - logger.info(`Rejecting...`) - await sendTransaction(cli.wallet, disputeManager, 'rejectDispute', ...[disputeID]) -} - -export const draw = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const disputeManager = cli.contracts.DisputeManager - const disputeID = cliArgs.disputeID - logger.info(`Drawing...`) - await sendTransaction(cli.wallet, disputeManager, 'drawDispute', ...[disputeID]) -} - -export const disputeManagerCommand = { - command: 'disputeManager', - describe: 'Dispute manager calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'query-dispute-conflict-test', - describe: 'Just create any query dispute to test the subgraph', - handler: async (argv: CLIArgs): Promise => { - return createTestQueryDisputeConflict(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'indexing-dispute-test', - describe: 'Just create any query dispute to test the subgraph', - handler: async (argv: CLIArgs): Promise => { - return createTestIndexingDispute(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'accept', - describe: 'Accept a dispute', - builder: (yargs: Argv) => { - return yargs.option('disputeID', { - description: 'The Dispute ID in question', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return accept(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'reject', - describe: 'Reject a dispute', - builder: (yargs: Argv) => { - return yargs.option('disputeID', { - description: 'The Dispute ID in question', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return reject(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'draw', - describe: 'Draw a dispute', - builder: (yargs: Argv) => { - return yargs.option('disputeID', { - description: 'The Dispute ID in question', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return draw(await loadEnv(argv), argv) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/ens.ts b/packages/contracts/cli/commands/contracts/ens.ts deleted file mode 100644 index 48a990d0f..000000000 --- a/packages/contracts/cli/commands/contracts/ens.ts +++ /dev/null @@ -1,74 +0,0 @@ -import yargs, { Argv } from 'yargs' -import { utils } from 'ethers' - -import { sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { logger } from '../../logging' - -export const registerTestName = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const name = cliArgs.name - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const testRegistrar = (cli.contracts as any).ITestRegistrar - const normalizedName = name.toLowerCase() - const labelNameFull = `${normalizedName}.${'eth'}` - const labelHashFull = utils.namehash(labelNameFull) - const label = utils.keccak256(utils.toUtf8Bytes(normalizedName)) - logger.info(`Namehash for ${labelNameFull}: ${labelHashFull}`) - logger.info(`Registering ${name} with ${cli.walletAddress} on the test registrar`) - await sendTransaction(cli.wallet, testRegistrar, 'register', [label, cli.walletAddress]) -} -export const checkOwner = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const name = cliArgs.name - const ens = cli.contracts.IENS - const node = nameToNode(name) - const res = await ens.owner(node) - logger.info(`owner = ${res}`) -} - -export const nameToNode = (name: string): string => { - const node = utils.namehash(`${name}.eth`) - logger.info(`Name: ${name}`) - logger.info(`Node: ${node}`) - return node -} - -export const ensCommand = { - command: 'ens', - describe: 'ENS contract calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'registerTestName', - describe: 'Register a name on the test registrar', - builder: (yargs: Argv) => { - return yargs.option('name', { - description: 'Name being registered', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return registerTestName(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'checkOwner', - describe: 'Check the owner of a name', - builder: (yargs: Argv) => { - return yargs.option('name', { - description: 'Name being checked', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return checkOwner(await loadEnv(argv), argv) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/gns.ts b/packages/contracts/cli/commands/contracts/gns.ts deleted file mode 100644 index 89c71e92f..000000000 --- a/packages/contracts/cli/commands/contracts/gns.ts +++ /dev/null @@ -1,399 +0,0 @@ -import yargs, { Argv } from 'yargs' -import { parseGRT } from '@graphprotocol/common-ts' - -import { logger } from '../../logging' -import { sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { nameToNode } from './ens' -import { IPFS, pinMetadataToIPFS, buildSubgraphID, ensureGRTAllowance } from '../../helpers' - -export const setDefaultName = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const graphAccount = cliArgs.graphAccount - const name = cliArgs.name - const nameSystem = 0 // 0 == ens - const node = nameToNode(name) - const gns = cli.contracts.GNS - - logger.info(`Setting default name as ${name} for ${graphAccount}...`) - await sendTransaction(cli.wallet, gns, 'setDefaultName', [graphAccount, nameSystem, node, name]) -} - -export const publishNewSubgraph = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const ipfs = cliArgs.ipfs - const subgraphDeploymentID = cliArgs.subgraphDeploymentID - const versionPath = cliArgs.versionPath - const subgraphPath = cliArgs.subgraphPath - - const subgraphDeploymentIDBytes = IPFS.ipfsHashToBytes32(subgraphDeploymentID) - const versionHashBytes = await pinMetadataToIPFS(ipfs, 'version', versionPath) - const subgraphHashBytes = await pinMetadataToIPFS(ipfs, 'subgraph', subgraphPath) - const gns = cli.contracts.GNS - - logger.info(`Publishing new subgraph for ${cli.walletAddress}...`) - await sendTransaction(cli.wallet, gns, 'publishNewSubgraph', [ - subgraphDeploymentIDBytes, - versionHashBytes, - subgraphHashBytes, - ]) -} - -export const publishNewVersion = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphID = cliArgs.subgraphID - const ipfs = cliArgs.ipfs - const subgraphDeploymentID = cliArgs.subgraphDeploymentID - const versionPath = cliArgs.versionPath - - const subgraphDeploymentIDBytes = IPFS.ipfsHashToBytes32(subgraphDeploymentID) - const versionHashBytes = await pinMetadataToIPFS(ipfs, 'version', versionPath) - const gns = cli.contracts.GNS - - logger.info(`Publishing new subgraph version for ${subgraphID}...`) - await sendTransaction(cli.wallet, gns, 'publishNewVersion', [ - subgraphID, - subgraphDeploymentIDBytes, - versionHashBytes, - ]) -} - -export const deprecate = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphID = cliArgs.subgraphID - const gns = cli.contracts.GNS - logger.info(`Deprecating subgraph ${subgraphID}...`) - await sendTransaction(cli.wallet, gns, 'deprecateSubgraph', [subgraphID]) -} - -export const updateSubgraphMetadata = async ( - cli: CLIEnvironment, - cliArgs: CLIArgs, -): Promise => { - const ipfs = cliArgs.ipfs - const subgraphID = cliArgs.subgraphID - const subgraphPath = cliArgs.subgraphPath - const subgraphHashBytes = await pinMetadataToIPFS(ipfs, 'subgraph', subgraphPath) - const gns = cli.contracts.GNS - - logger.info(`Updating subgraph metadata for ${subgraphID}...`) - await sendTransaction(cli.wallet, gns, 'updateSubgraphMetadata', [subgraphID, subgraphHashBytes]) -} - -export const mintSignal = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphID = cliArgs.subgraphID - const tokens = parseGRT(cliArgs.tokens) - const gns = cli.contracts.GNS - - logger.info(`Minting signal for ${subgraphID}...`) - await sendTransaction(cli.wallet, gns, 'mintSignal', [subgraphID, tokens, 0]) -} - -export const burnSignal = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphID = cliArgs.subgraphID - const signal = cliArgs.signal - const gns = cli.contracts.GNS - - logger.info(`Burning signal from ${subgraphID}...`) - await sendTransaction(cli.wallet, gns, 'burnSignal', [subgraphID, signal, 0]) -} - -export const withdraw = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphID = cliArgs.subgraphID - const gns = cli.contracts.GNS - - logger.info(`Withdrawing locked GRT from subgraph ${subgraphID}...`) - await sendTransaction(cli.wallet, gns, 'withdraw', [subgraphID]) -} - -export const publishAndSignal = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - // parse args - const ipfs = cliArgs.ipfs - const subgraphDeploymentID = cliArgs.subgraphDeploymentID - const versionPath = cliArgs.versionPath - const subgraphPath = cliArgs.subgraphPath - const tokens = parseGRT(cliArgs.tokens) - - // pin to IPFS - const subgraphDeploymentIDBytes = IPFS.ipfsHashToBytes32(subgraphDeploymentID) - const versionHashBytes = await pinMetadataToIPFS(ipfs, 'version', versionPath) - const subgraphHashBytes = await pinMetadataToIPFS(ipfs, 'subgraph', subgraphPath) - - // craft transaction - const GNS = cli.contracts.GNS - - // build publish tx - const publishTx = await GNS.populateTransaction.publishNewSubgraph( - subgraphDeploymentIDBytes, - versionHashBytes, - subgraphHashBytes, - ) - - // build mint tx - const subgraphID = buildSubgraphID( - cli.walletAddress, - await GNS.nextAccountSeqID(cli.walletAddress), - ) - const mintTx = await GNS.populateTransaction.mintSignal(subgraphID, tokens, 0) - - // ensure approval - await ensureGRTAllowance(cli.wallet, GNS.address, tokens, cli.contracts.GraphToken) - - // send multicall transaction - logger.info(`Publishing and minting on new subgraph for ${cli.walletAddress}...`) - await sendTransaction(cli.wallet, GNS, 'multicall', [[publishTx.data, mintTx.data]]) -} - -export const gnsCommand = { - command: 'gns', - describe: 'GNS contract calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'setDefaultName', - describe: 'Set default name for the graph explorer', - builder: (yargs: Argv) => { - return yargs - .option('graphAccount', { - description: 'Graph account getting its name set', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('name', { - description: 'Name on ENS being registered', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return setDefaultName(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'publishNewSubgraph', - describe: 'Publish a new subgraph to the GNS', - builder: (yargs: Argv) => { - return yargs - .option('ipfs', { - description: 'ipfs endpoint. ex. https://api.thegraph.com/ipfs/', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('subgraphDeploymentID', { - description: 'subgraph deployment ID in base58', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('versionPath', { - description: ` filepath to metadata. With JSON format:\n - "description": "", - "label": ""`, - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('subgraphPath', { - description: ` filepath to metadata. With JSON format:\n - "description": "", - "displayName": "", - "image": "", - "codeRepository": "", - "website": "",`, - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return publishNewSubgraph(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'publishNewVersion', - describe: 'Publish a new subgraph version', - builder: (yargs: Argv) => { - return yargs - .option('subgraphID', { - description: 'Subgraph identifier', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('ipfs', { - description: 'ipfs endpoint. ex. https://api.thegraph.com/ipfs/', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('subgraphDeploymentID', { - description: 'subgraph deployment ID in base58', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('versionPath', { - description: ` filepath to metadata. With JSON format:\n - "description": "", - "label": ""`, - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return publishNewVersion(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'deprecate', - describe: 'Deprecate a subgraph', - builder: (yargs: Argv) => { - return yargs.option('subgraphID', { - description: 'Subgraph identifier', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return deprecate(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'updateSubgraphMetadata', - describe: 'Update a subgraphs metadata', - builder: (yargs: Argv) => { - return yargs - .option('subgraphID', { - description: 'Subgraph identifier', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('subgraphPath', { - description: ` filepath to metadata. With JSON format:\n - "description": "", - "displayName": "", - "image": "", - "codeRepository": "", - "website": "",`, - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return updateSubgraphMetadata(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'mintSignal', - describe: 'Mint Name Signal by depositing tokens', - builder: (yargs: Argv) => { - return yargs - .option('subgraphID', { - description: 'Subgraph identifier', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('tokens', { - description: 'Amount of tokens to deposit', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return mintSignal(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'burnSignal', - describe: 'Burn Name Signal and receive tokens', - builder: (yargs: Argv) => { - return yargs - .option('subgraphID', { - description: 'Subgraph identifier', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('signal', { - description: 'Amount of signal to burn', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return burnSignal(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'withdraw', - describe: 'Withdraw GRT from a deprecated subgraph', - builder: (yargs: Argv) => { - return yargs.option('subgraphID', { - description: 'Subgraph identifier', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return withdraw(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'publishAndSignal', - describe: 'Publish a new subgraph and add initial signal', - builder: (yargs: Argv) => { - return yargs - .option('ipfs', { - description: 'ipfs endpoint. ex. https://api.thegraph.com/ipfs/', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('subgraphDeploymentID', { - description: 'subgraph deployment ID in base58', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('versionPath', { - description: ` filepath to metadata. With JSON format:\n - "description": "", - "label": ""`, - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('subgraphPath', { - description: ` filepath to metadata. With JSON format:\n - "description": "", - "displayName": "", - "image": "", - "codeRepository": "", - "website": "",`, - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('tokens', { - description: 'Amount of tokens to deposit', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return publishAndSignal(await loadEnv(argv), argv) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/governance.ts b/packages/contracts/cli/commands/contracts/governance.ts deleted file mode 100644 index 412171ede..000000000 --- a/packages/contracts/cli/commands/contracts/governance.ts +++ /dev/null @@ -1,121 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { logger } from '../../logging' - -export const createProposal = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const id = cliArgs.id - const votes = cliArgs.votes - const metadata = cliArgs.metadata - const resolution = cliArgs.resolution - const governance = cli.contracts.GraphGovernance - - logger.info(`Creating proposal ${id}...`) - await sendTransaction(cli.wallet, governance, 'createProposal', [id, votes, metadata, resolution]) -} - -export const upgradeProposal = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const id = cliArgs.id - const votes = cliArgs.votes - const metadata = cliArgs.metadata - const resolution = cliArgs.resolution - const governance = cli.contracts.GraphGovernance - - logger.info(`Upgrade proposal ${id}...`) - await sendTransaction(cli.wallet, governance, 'upgradeProposal', [ - id, - votes, - metadata, - resolution, - ]) -} - -export const governanceCommand = { - command: 'governance', - describe: 'Graph governance contract calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'createProposal', - describe: 'Create a proposal', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('id', { - description: 'Proposal ID', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('votes', { - description: 'IPFS hash in bytes32', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('metadata', { - description: 'IPFS hash in bytes32', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('resolution', { - description: 'Resolution. 1 = Accepted, 2 = Rejected ', - type: 'number', - requiresArg: true, - demandOption: true, - }) - .option('b', { - alias: 'build-tx', - description: - 'Build the acceptProxy tx and print it. Then use tx data with a multisig', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return createProposal(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'upgradeProposal', - describe: 'Upgrade a proposal', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('id', { - description: 'Proposal ID', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('votes', { - description: 'IPFS hash in bytes32', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('metadata', { - description: 'IPFS hash in bytes32', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('resolution', { - description: 'Resolution. 1 = Accepted, 2 = Rejected ', - type: 'number', - requiresArg: true, - demandOption: true, - }) - .option('b', { - alias: 'build-tx', - description: - 'Build the acceptProxy tx and print it. Then use tx data with a multisig', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return upgradeProposal(await loadEnv(argv), argv) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/graphToken.ts b/packages/contracts/cli/commands/contracts/graphToken.ts deleted file mode 100644 index ed2e0a158..000000000 --- a/packages/contracts/cli/commands/contracts/graphToken.ts +++ /dev/null @@ -1,165 +0,0 @@ -import yargs, { Argv } from 'yargs' -import { parseGRT } from '@graphprotocol/common-ts' - -import { logger } from '../../logging' -import { sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' - -export const mint = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const amount = parseGRT(cliArgs.amount) - const account = cliArgs.account - const graphToken = cli.contracts.GraphToken - - logger.info(`Minting ${cliArgs.amount} tokens for spender ${account}...`) - await sendTransaction(cli.wallet, graphToken, 'mint', [account, amount]) -} - -export const burn = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const amount = parseGRT(cliArgs.amount) - const graphToken = cli.contracts.GraphToken - - logger.info(`Burning ${cliArgs.amount} tokens...`) - await sendTransaction(cli.wallet, graphToken, 'burn', [amount]) -} - -export const transfer = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const amount = parseGRT(cliArgs.amount) - const account = cliArgs.account - const graphToken = cli.contracts.GraphToken - - logger.info(`Transferring ${cliArgs.amount} tokens to spender ${account}...`) - await sendTransaction(cli.wallet, graphToken, 'transfer', [account, amount]) -} - -export const approve = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const amount = parseGRT(cliArgs.amount) - const account = cliArgs.account - const graphToken = cli.contracts.GraphToken - - logger.info(`Approving ${cliArgs.amount} tokens for spender ${account} to spend...`) - await sendTransaction(cli.wallet, graphToken, 'approve', [account, amount]) -} - -export const allowance = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const account = cliArgs.account - const spender = cliArgs.spender - const graphToken = cli.contracts.GraphToken - - logger.info(`Checking ${account} allowance set for spender ${spender}...`) - const res = await graphToken.allowance(account, spender) - logger.info(`allowance = ${res}`) -} - -export const graphTokenCommand = { - command: 'graphToken', - describe: 'Graph Token contract calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'mint', - describe: 'Mint GRT', - builder: (yargs: Argv) => { - return yargs - .option('account', { - description: 'The account getting sent minted GRT', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of tokens. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return mint(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'burn', - describe: 'Burn GRT', - builder: (yargs: Argv) => { - return yargs.option('amount', { - description: 'Amount of tokens. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return burn(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'transfer', - describe: 'Transfer GRT', - builder: (yargs: Argv) => { - return yargs - .option('account', { - description: 'The account receiving GRT', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of tokens. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return transfer(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'approve', - describe: 'Approve GRT', - builder: (yargs: Argv) => { - return yargs - .option('account', { - description: 'The account being approved as a spender', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of tokens. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return approve(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'allowance', - describe: 'Check GRT allowance', - builder: (yargs: Argv) => { - return yargs - .option('account', { - description: 'The account who gave an allowance', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('spender', { - description: 'The spender', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return allowance(await loadEnv(argv), argv) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/index.ts b/packages/contracts/cli/commands/contracts/index.ts deleted file mode 100644 index 60bb2e239..000000000 --- a/packages/contracts/cli/commands/contracts/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { curationCommand } from './curation' -import { serviceRegistryCommand } from './serviceRegistry' -import { ensCommand } from './ens' -import { gnsCommand } from './gns' -import { graphTokenCommand } from './graphToken' -import { stakingCommand } from './staking' -import { anyCommand } from './any' -import { governanceCommand } from './governance' - -import { disputeManagerCommand } from './disputeManager' - -export const contractsCommand = { - command: 'contracts', - describe: 'Contract calls for all contracts', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command(curationCommand) - .command(serviceRegistryCommand) - .command(ensCommand) - .command(gnsCommand) - .command(graphTokenCommand) - .command(stakingCommand) - .command(anyCommand) - .command(disputeManagerCommand) - .command(governanceCommand) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/serviceRegistry.ts b/packages/contracts/cli/commands/contracts/serviceRegistry.ts deleted file mode 100644 index 541c340aa..000000000 --- a/packages/contracts/cli/commands/contracts/serviceRegistry.ts +++ /dev/null @@ -1,62 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { logger } from '../../logging' -import { sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' - -export const register = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const url = cliArgs.url - const geoHash = cliArgs.geoHash - const serviceRegistry = cli.contracts.ServiceRegistry - - logger.info(`Registering indexer ${cli.walletAddress} with url ${url} and geoHash ${geoHash}`) - await sendTransaction(cli.wallet, serviceRegistry, 'register', [url, geoHash]) -} -export const unregister = async (cli: CLIEnvironment): Promise => { - const serviceRegistry = cli.contracts.ServiceRegistry - - logger.info(`Unregistering indexer ${cli.walletAddress}`) - await sendTransaction(cli.wallet, serviceRegistry, 'unregister') -} - -export const serviceRegistryCommand = { - command: 'serviceRegistry', - describe: 'Service Registry contract calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'register', - describe: 'Register an indexer in the service registry', - builder: (yargs: Argv) => { - return yargs - .option('u', { - alias: 'url', - description: 'URL of the indexer', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('g', { - alias: 'geoHash', - description: 'GeoHash of the indexer', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return register(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'unregister', - describe: 'Unregister an indexer in the service registry', - handler: async (argv: CLIArgs): Promise => { - return unregister(await loadEnv(argv)) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/contracts/staking.ts b/packages/contracts/cli/commands/contracts/staking.ts deleted file mode 100644 index c9ed77719..000000000 --- a/packages/contracts/cli/commands/contracts/staking.ts +++ /dev/null @@ -1,342 +0,0 @@ -import yargs, { Argv } from 'yargs' -import { parseGRT } from '@graphprotocol/common-ts' - -import { logger } from '../../logging' -import { sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' - -export const stake = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const amount = parseGRT(cliArgs.amount) - const staking = cli.contracts.Staking - - logger.info(`Staking ${cliArgs.amount} tokens...`) - await sendTransaction(cli.wallet, staking, 'stake', [amount]) -} - -export const unstake = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const amount = parseGRT(cliArgs.amount) - const staking = cli.contracts.Staking - - logger.info(`Unstaking ${cliArgs.amount} tokens...`) - await sendTransaction(cli.wallet, staking, 'unstake', [amount]) -} - -export const withdraw = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const staking = cli.contracts.Staking - - logger.info(`Withdrawing ${cliArgs.amount} tokens...`) - await sendTransaction(cli.wallet, staking, 'withdraw') -} - -export const allocate = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const subgraphDeploymentID = cliArgs.subgraphDeploymentID - const amount = parseGRT(cliArgs.amount) - const allocationID = cliArgs.allocationID - const metadata = cliArgs.metadata - const proof = cliArgs.proof - const staking = cli.contracts.Staking - - logger.info(`Allocating ${cliArgs.amount} tokens on ${subgraphDeploymentID}...`) - await sendTransaction(cli.wallet, staking, 'allocateFrom', [ - cli.walletAddress, - subgraphDeploymentID, - amount, - allocationID, - metadata, - proof, - ]) -} - -export const closeAllocation = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const allocationID = cliArgs.allocationID - const poi = cliArgs.poi - const staking = cli.contracts.Staking - - logger.info(`Closing allocation ${allocationID} with poi ${poi}...`) - await sendTransaction(cli.wallet, staking, 'closeAllocation', [allocationID, poi]) -} - -export const delegate = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const indexer = cliArgs.indexer - const amount = parseGRT(cliArgs.amount) - const staking = cli.contracts.Staking - - logger.info(`Delegating ${cliArgs.amount} tokens to indexer ${indexer}...`) - await sendTransaction(cli.wallet, staking, 'delegate', [indexer, amount]) -} - -export const undelegate = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const indexer = cliArgs.indexer - const amount = parseGRT(cliArgs.amount) - const staking = cli.contracts.Staking - - logger.info(`Undelegating ${cliArgs.amount} tokens from indexer ${indexer}...`) - await sendTransaction(cli.wallet, staking, 'undelegate', [indexer, amount]) -} - -export const withdrawDelegated = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const indexer = cliArgs.indexer - const newIndexer = cliArgs.newIndexer - const staking = cli.contracts.Staking - - if (newIndexer != '0x0000000000000000000000000000000000000000') { - logger.info(`Withdrawing from ${indexer} to new indexer ${newIndexer}...`) - } else { - logger.info(`Withdrawing from ${indexer} without restaking`) - } - await sendTransaction(cli.wallet, staking, 'withdrawDelegated', [indexer, newIndexer]) -} - -export const setDelegationParameters = async ( - cli: CLIEnvironment, - cliArgs: CLIArgs, -): Promise => { - const indexingRewardCut = cliArgs.indexingRewardCut - const queryFeeCut = cliArgs.queryFeeCut - const cooldownBlocks = cliArgs.cooldownBlocks - const staking = cli.contracts.Staking - - logger.info(`Setting the following delegation parameters for indexer ${cli.walletAddress} - indexingRewardCut = ${indexingRewardCut} - queryFeeCut = ${queryFeeCut} - cooldownBlocks (deprecated) = ${cooldownBlocks} - `) - await sendTransaction(cli.wallet, staking, 'setDelegationParameters', [ - indexingRewardCut, - queryFeeCut, - cooldownBlocks, - ]) -} -export const setOperator = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const operator = cliArgs.operator - const allowed = cliArgs.allowed - const staking = cli.contracts.Staking - logger.info(`Setting operator ${operator} to ${allowed} for account ${cli.walletAddress}`) - await sendTransaction(cli.wallet, staking, 'setOperator', [operator, allowed]) -} - -export const stakingCommand = { - command: 'staking', - describe: 'Staking contract calls', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command({ - command: 'stake', - describe: 'Stake GRT', - builder: (yargs: Argv) => { - return yargs.option('amount', { - description: 'Amount of tokens to stake. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return stake(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'unstake', - describe: 'Unstake GRT', - builder: (yargs: Argv) => { - return yargs.option('amount', { - description: 'Amount of tokens to unstake. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return unstake(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'withdraw', - describe: 'Withdraw unlocked GRT', - handler: async (argv: CLIArgs): Promise => { - return withdraw(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'allocate', - describe: 'Allocate GRT on a subgraph deployment', - builder: (yargs: Argv) => { - return yargs - .option('subgraphDeploymentID', { - description: 'The subgraph deployment ID being allocated on', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of tokens being allocated. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('allocationID', { - description: 'Address used by the indexer as destination of funds of state channel', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('metadata', { - description: 'IPFS hash of the metadata for the allocation', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('proof', { - description: - 'A 65-bytes Ethereum signed message of `keccak256(indexerAddress,allocationID)`', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return allocate(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'close-allocation', - describe: 'Close an allocation', - builder: (yargs: Argv) => { - return yargs - .option('allocationID', { - description: 'The allocation being closed', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('poi', { - description: 'Proof of indexing', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return closeAllocation(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'delegate', - describe: 'Delegate GRT', - builder: (yargs: Argv) => { - return yargs - .option('indexer', { - description: 'Indexer being delegated to', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of tokens. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return delegate(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'undelegate', - describe: 'Undelegate GRT', - builder: (yargs: Argv) => { - return yargs - .option('indexer', { - description: 'Indexer being undelegated on', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('amount', { - description: 'Amount of tokens. CLI converts to a BN with 10^18', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return undelegate(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'withdrawDelegated', - describe: 'Withdrawn unlocked delegated GRT', - builder: (yargs: Argv) => { - return yargs - .option('indexer', { - description: 'Indexer being withdrawn from to', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('newIndexer', { - description: - 'New indexer being delegated to. if address(0) it will return the tokens', - type: 'string', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return withdrawDelegated(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'setDelegationParameters', - describe: 'Sets the delegation parameters for an indexer', - builder: (yargs: Argv) => { - return yargs - .option('indexingRewardCut', { - description: 'Percentage of indexing rewards left for delegators', - type: 'number', - requiresArg: true, - demandOption: true, - }) - .option('queryFeeCut', { - description: 'Percentage of query fees left for delegators', - type: 'number', - requiresArg: true, - demandOption: true, - }) - .option('cooldownBlocks', { - description: 'Period that need to pass to update delegation parameters (deprecated)', - type: 'number', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return setDelegationParameters(await loadEnv(argv), argv) - }, - }) - .command({ - command: 'setOperator', - describe: 'Set the operator for a graph account', - builder: (yargs: Argv) => { - return yargs - .option('operator', { - description: 'Address of the operator', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('allowed', { - description: 'Set to true to be an operator, false to revoke', - type: 'boolean', - requiresArg: true, - demandOption: true, - }) - }, - handler: async (argv: CLIArgs): Promise => { - return setOperator(await loadEnv(argv), argv) - }, - }) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/deploy.ts b/packages/contracts/cli/commands/deploy.ts deleted file mode 100644 index d5ebde498..000000000 --- a/packages/contracts/cli/commands/deploy.ts +++ /dev/null @@ -1,103 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { - getContractAt, - deployContract, - deployContractAndSave, - deployContractWithProxy, - deployContractWithProxyAndSave, -} from '../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../env' -import { logger } from '../logging' -import { confirm } from '../helpers' - -export const deploy = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const contractName = cliArgs.contract - const initArgs = cliArgs.init - const deployType = cliArgs.type - const buildAcceptProxyTx = cliArgs.buildTx - const skipConfirmation = cliArgs.skipConfirmation - - // Ensure action - const sure = await confirm(`Are you sure to deploy ${contractName}?`, skipConfirmation) - if (!sure) return - - // Deploy contract - const contractArgs = initArgs ? initArgs.split(',') : [] - switch (deployType) { - case 'deploy': - logger.info(`Deploying contract ${contractName}...`) - await deployContract(contractName, contractArgs, cli.wallet) - break - case 'deploy-save': - logger.info(`Deploying contract ${contractName} and saving to address book...`) - await deployContractAndSave(contractName, contractArgs, cli.wallet, cli.addressBook) - break - case 'deploy-with-proxy': - // Get the GraphProxyAdmin to own the GraphProxy for this contract - const proxyAdminEntry = cli.addressBook.getEntry('GraphProxyAdmin') - if (!proxyAdminEntry) { - throw new Error('GraphProxyAdmin not detected in the config, must be deployed first!') - } - const proxyAdmin = getContractAt('GraphProxyAdmin', proxyAdminEntry.address) - - logger.info(`Deploying contract ${contractName} with proxy ...`) - await deployContractWithProxy( - proxyAdmin, - contractName, - contractArgs, - cli.wallet, - buildAcceptProxyTx, - ) - break - case 'deploy-with-proxy-save': - logger.info(`Deploying contract ${contractName} with proxy and saving to address book...`) - await deployContractWithProxyAndSave( - contractName, - contractArgs, - cli.wallet, - cli.addressBook, - buildAcceptProxyTx, - ) - break - default: - logger.error('Please provide the correct option for deploy type') - } -} - -export const deployCommand = { - command: 'deploy', - describe: 'Deploy contract', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('x', { - alias: 'init', - description: 'Init arguments as comma-separated values', - type: 'string', - requiresArg: true, - }) - .option('c', { - alias: 'contract', - description: 'Contract name to deploy', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('t', { - alias: 'type', - description: 'Choose deploy, deploy-save, deploy-with-proxy, deploy-with-proxy-save', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('b', { - alias: 'build-tx', - description: 'Build the acceptProxy tx and print it. Then use tx data with a multisig', - default: false, - type: 'boolean', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return deploy(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/migrate.ts b/packages/contracts/cli/commands/migrate.ts deleted file mode 100644 index 079e1d731..000000000 --- a/packages/contracts/cli/commands/migrate.ts +++ /dev/null @@ -1,198 +0,0 @@ -import { constants, providers, utils } from 'ethers' -import yargs, { Argv } from 'yargs' - -import { logger } from '../logging' -import { loadCallParams, readConfig, getContractConfig } from '../config' -import { cliOpts } from '../defaults' -import { - isContractDeployed, - deployContractAndSave, - deployContractWithProxyAndSave, - sendTransaction, -} from '../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../env' -import { chainIdIsL2 } from '../cross-chain' -import { confirm } from '../helpers' - -const { EtherSymbol } = constants -const { formatEther } = utils - -// Contracts are deployed in the order defined in this list -let allContracts = [ - 'GraphProxyAdmin', - 'BancorFormula', - 'Controller', - 'EpochManager', - 'GraphToken', - 'GraphCurationToken', - 'ServiceRegistry', - 'Curation', - 'SubgraphNFTDescriptor', - 'SubgraphNFT', - 'L1GNS', - 'StakingExtension', - 'L1Staking', - 'RewardsManager', - 'DisputeManager', - 'AllocationExchange', - 'L1GraphTokenGateway', - 'BridgeEscrow', -] - -const l2Contracts = [ - 'GraphProxyAdmin', - 'Controller', - 'EpochManager', - 'L2GraphToken', - 'GraphCurationToken', - 'ServiceRegistry', - 'L2Curation', - 'SubgraphNFTDescriptor', - 'SubgraphNFT', - 'L2GNS', - 'StakingExtension', - 'L2Staking', - 'RewardsManager', - 'DisputeManager', - 'AllocationExchange', - 'L2GraphTokenGateway', -] - -export const migrate = async ( - cli: CLIEnvironment, - cliArgs: CLIArgs, - autoMine = false, -): Promise => { - const graphConfigPath = cliArgs.graphConfig - const force = cliArgs.force - const contractName = cliArgs.contract - const chainId = cli.chainId - const skipConfirmation = cliArgs.skipConfirmation - - // Ensure action - const sure = await confirm('Are you sure you want to migrate contracts?', skipConfirmation) - if (!sure) return - - if (chainId == 1337) { - allContracts = ['EthereumDIDRegistry', ...allContracts] - await setAutoMine(cli.wallet.provider as providers.JsonRpcProvider, true) - } else if (chainIdIsL2(chainId)) { - allContracts = l2Contracts - } - - logger.info(`>>> Migrating contracts <<<\n`) - - const graphConfig = readConfig(graphConfigPath) - - //////////////////////////////////////// - // Deploy contracts - - // Filter contracts to be deployed - if (contractName && !allContracts.includes(contractName)) { - logger.error(`Contract ${contractName} not found in address book`) - return - } - const deployContracts = contractName ? [contractName] : allContracts - const pendingContractCalls = [] - - // Deploy contracts - logger.info(`>>> Contracts deployment\n`) - for (const name of deployContracts) { - // Get address book info - const addressEntry = cli.addressBook.getEntry(name) - const savedAddress = addressEntry && addressEntry.address - - logger.info(`= Deploy: ${name}`) - - // Check if contract already deployed - const isDeployed = await isContractDeployed( - name, - savedAddress, - cli.addressBook, - cli.wallet.provider, - ) - if (!force && isDeployed) { - logger.info(`${name} is up to date, no action required`) - logger.info(`Address: ${savedAddress}\n`) - continue - } - - // Get config and deploy contract - const contractConfig = getContractConfig(graphConfig, cli.addressBook, name, cli) - const deployFn = contractConfig.proxy ? deployContractWithProxyAndSave : deployContractAndSave - const contract = await deployFn( - name, - contractConfig.params.map((a) => a.value), // keep only the values - cli.wallet, - cli.addressBook, - ) - logger.info('') - - // Defer contract calls after deploying every contract - if (contractConfig.calls) { - pendingContractCalls.push({ name, contract, calls: contractConfig.calls }) - } - } - logger.info('Contract deployments done! Contract calls are next') - - //////////////////////////////////////// - // Run contracts calls - - logger.info('') - logger.info(`>>> Contracts calls\n`) - if (pendingContractCalls.length > 0) { - for (const entry of pendingContractCalls) { - if (entry.calls.length == 0) continue - - logger.info(`= Config: ${entry.name}`) - for (const call of entry.calls) { - logger.info(`\n* Calling ${call.fn}:`) - await sendTransaction( - cli.wallet, - entry.contract, - call.fn, - loadCallParams(call.params, cli.addressBook, cli), - ) - } - logger.info('') - } - } else { - logger.info('Nothing to do') - } - - //////////////////////////////////////// - // Print summary - logger.info('') - logger.info(`>>> Summary\n`) - logger.info('All done!') - const spent = formatEther(cli.balance.sub(await cli.wallet.getBalance())) - const nTx = (await cli.wallet.getTransactionCount()) - cli.nonce - logger.info(`Sent ${nTx} transaction${nTx === 1 ? '' : 's'} & spent ${EtherSymbol} ${spent}`) - - if (chainId == 1337) { - await setAutoMine(cli.wallet.provider as providers.JsonRpcProvider, autoMine) - } -} - -const setAutoMine = async (provider: providers.JsonRpcProvider, automine: boolean) => { - try { - await provider.send('evm_setAutomine', [automine]) - } catch (error) { - logger.warn('The method evm_setAutomine does not exist/is not available!') - } -} - -export const migrateCommand = { - command: 'migrate', - describe: 'Migrate contracts', - builder: (yargs: Argv): yargs.Argv => { - return yargs.option('c', cliOpts.graphConfig).option('n', { - alias: 'contract', - description: 'Contract name to deploy (all if not set)', - type: 'string', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return migrate(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/protocol/configure-bridge.ts b/packages/contracts/cli/commands/protocol/configure-bridge.ts deleted file mode 100644 index c0273ca33..000000000 --- a/packages/contracts/cli/commands/protocol/configure-bridge.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { logger } from '../../logging' -import { getAddressBook } from '../../address-book' -import { sendTransaction } from '../../network' -import { chainIdIsL2, l1ToL2ChainIdMap, l2ToL1ChainIdMap } from '../../cross-chain' - -export const configureL1Bridge = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - logger.info(`>>> Setting L1 Bridge Configuration <<<\n`) - - if (chainIdIsL2(cli.chainId)) { - throw new Error('Cannot set L1 configuration on an L2 network!') - } - const l2ChainId = cliArgs.l2ChainId ? cliArgs.l2ChainId : l1ToL2ChainIdMap[cli.chainId] - logger.info('Connecting with the contracts on L2 chainId ' + l2ChainId) - const l2AddressBook = getAddressBook(cliArgs.addressBook, l2ChainId) - const arbAddressBook = getAddressBook(cliArgs.arbAddressBook, cli.chainId.toString()) - - // Gateway - const gateway = cli.contracts['L1GraphTokenGateway'] - - const l2GRT = l2AddressBook.getEntry('L2GraphToken') - logger.info('L2 GRT address: ' + l2GRT.address) - await sendTransaction(cli.wallet, gateway, 'setL2TokenAddress', [l2GRT.address]) - - const l2GatewayCounterpart = l2AddressBook.getEntry('L2GraphTokenGateway') - logger.info('L2 Gateway address: ' + l2GatewayCounterpart.address) - await sendTransaction(cli.wallet, gateway, 'setL2CounterpartAddress', [ - l2GatewayCounterpart.address, - ]) - - // Escrow - const bridgeEscrow = cli.contracts.BridgeEscrow - logger.info('Escrow address: ' + bridgeEscrow.address) - await sendTransaction(cli.wallet, gateway, 'setEscrowAddress', [bridgeEscrow.address]) - await sendTransaction(cli.wallet, bridgeEscrow, 'approveAll', [gateway.address]) - - const l1Inbox = arbAddressBook.getEntry('IInbox') - const l1Router = arbAddressBook.getEntry('L1GatewayRouter') - logger.info( - 'L1 Inbox address: ' + l1Inbox.address + ' and L1 Router address: ' + l1Router.address, - ) - await sendTransaction(cli.wallet, gateway, 'setArbitrumAddresses', [ - l1Inbox.address, - l1Router.address, - ]) - - // GNS - const gns = cli.contracts.L1GNS - const l2GNSCounterpart = l2AddressBook.getEntry('L2GNS') - logger.info('L2 GNS address: ' + l2GNSCounterpart.address) - await sendTransaction(cli.wallet, gns, 'setCounterpartGNSAddress', [l2GNSCounterpart.address]) - await sendTransaction(cli.wallet, gateway, 'addToCallhookAllowlist', [gns.address]) - - // Staking - const staking = cli.contracts.L1Staking - const l2StakingCounterpart = l2AddressBook.getEntry('L2Staking') - logger.info('L2 Staking address: ' + l2StakingCounterpart.address) - await sendTransaction(cli.wallet, staking, 'setCounterpartStakingAddress', [ - l2StakingCounterpart.address, - ]) - await sendTransaction(cli.wallet, gateway, 'addToCallhookAllowlist', [staking.address]) -} - -export const configureL2Bridge = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - logger.info(`>>> Setting L2 Bridge Configuration <<<\n`) - - if (!chainIdIsL2(cli.chainId)) { - throw new Error('Cannot set L2 configuration on an L1 network!') - } - const l1ChainId = cliArgs.l1ChainId ? cliArgs.l1ChainId : l2ToL1ChainIdMap[cli.chainId] - logger.info('Connecting with the contracts on L1 chainId ' + l1ChainId) - const l1AddressBook = getAddressBook(cliArgs.addressBook, l1ChainId) - const arbAddressBook = getAddressBook(cliArgs.arbAddressBook, cli.chainId.toString()) - - // Gateway - const gateway = cli.contracts['L2GraphTokenGateway'] - const token = cli.contracts['L2GraphToken'] - - const l1GRT = l1AddressBook.getEntry('GraphToken') - logger.info('L1 GRT address: ' + l1GRT.address) - await sendTransaction(cli.wallet, gateway, 'setL1TokenAddress', [l1GRT.address]) - await sendTransaction(cli.wallet, token, 'setL1Address', [l1GRT.address]) - - const l1Counterpart = l1AddressBook.getEntry('L1GraphTokenGateway') - logger.info('L1 Gateway address: ' + l1Counterpart.address) - await sendTransaction(cli.wallet, gateway, 'setL1CounterpartAddress', [l1Counterpart.address]) - - const l2Router = arbAddressBook.getEntry('L2GatewayRouter') - logger.info('L2 Router address: ' + l2Router.address) - await sendTransaction(cli.wallet, gateway, 'setL2Router', [l2Router.address]) - - logger.info('L2 Gateway address: ' + gateway.address) - await sendTransaction(cli.wallet, token, 'setGateway', [gateway.address]) - - // GNS - const gns = cli.contracts.L2GNS - const l1GNSCounterpart = l1AddressBook.getEntry('L1GNS') - logger.info('L1 GNS address: ' + l1GNSCounterpart.address) - await sendTransaction(cli.wallet, gns, 'setCounterpartGNSAddress', [l1GNSCounterpart.address]) - - // Staking - const staking = cli.contracts.L2Staking - const l1StakingCounterpart = l1AddressBook.getEntry('L1Staking') - logger.info('L1 Staking address: ' + l1StakingCounterpart.address) - await sendTransaction(cli.wallet, staking, 'setCounterpartStakingAddress', [ - l1StakingCounterpart.address, - ]) -} - -export const configureL1BridgeCommand = { - command: 'configure-l1-bridge [l2ChainId]', - describe: 'Configure L1/L2 bridge parameters (L1 side) using the address book', - handler: async (argv: CLIArgs): Promise => { - return configureL1Bridge(await loadEnv(argv), argv) - }, -} - -export const configureL2BridgeCommand = { - command: 'configure-l2-bridge [l1ChainId]', - describe: 'Configure L1/L2 bridge parameters (L2 side) using the address book', - handler: async (argv: CLIArgs): Promise => { - return configureL2Bridge(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/protocol/get.ts b/packages/contracts/cli/commands/protocol/get.ts deleted file mode 100644 index 299457ab7..000000000 --- a/packages/contracts/cli/commands/protocol/get.ts +++ /dev/null @@ -1,102 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { logger } from '../../logging' -import { getContractAt } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { ContractFunction } from 'ethers' - -import { ProtocolFunction } from './index' - -export const gettersList = { - // Staking - 'staking-slasher': { contract: 'Staking', name: 'slashers' }, - 'staking-thawing-period': { contract: 'Staking', name: 'thawingPeriod' }, - 'staking-max-allocation-epochs': { contract: 'Staking', name: 'maxAllocationEpochs' }, - 'staking-delegation-ratio': { contract: 'Staking', name: 'delegationRatio' }, - 'staking-delegation-unbonding-period': { contract: 'Staking', name: 'delegationUnbondingPeriod' }, - 'protocol-percentage': { contract: 'Staking', name: 'protocolPercentage' }, - // Curation - 'curation-reserve-ratio': { contract: 'Curation', name: 'defaultReserveRatio' }, - 'curation-percentage': { contract: 'Staking', name: 'curationPercentage' }, - 'curation-minimum-deposit': { contract: 'Curation', name: 'minimumCurationDeposit' }, - 'curation-tax-percentage': { contract: 'Curation', name: 'curationTaxPercentage' }, - 'curation-bonding-curve': { contract: 'Curation', name: 'bondingCurve' }, - // Disputes - 'disputes-arbitrator': { contract: 'DisputeManager', name: 'arbitrator' }, - 'disputes-minimum-deposit': { contract: 'DisputeManager', name: 'minimumDeposit' }, - 'disputes-reward-percentage': { contract: 'DisputeManager', name: 'fishermanRewardPercentage' }, - // Epochs - 'epochs-length': { contract: 'EpochManager', name: 'epochLength' }, - 'epochs-current': { contract: 'EpochManager', name: 'currentEpoch' }, - // Rewards - 'rewards-issuance-per-block': { contract: 'RewardsManager', name: 'issuancePerBlock' }, - 'subgraph-availability-oracle': { - contract: 'RewardsManager', - name: 'subgraphAvailabilityOracle', - }, - // GNS - 'gns-bonding-curve': { contract: 'GNS', name: 'bondingCurve' }, - 'gns-owner-tax-percentage': { contract: 'GNS', name: 'ownerTaxPercentage' }, - // Token - 'token-governor': { contract: 'GraphToken', name: 'governor' }, - 'token-supply': { contract: 'GraphToken', name: 'totalSupply' }, - // Controller - 'controller-governor': { contract: 'Controller', name: 'governor' }, - 'controller-get-contract-proxy': { contract: 'Controller', name: 'getContractProxy' }, - 'controller-get-paused': { contract: 'Controller', name: 'paused' }, - 'controller-get-partial-paused': { contract: 'Controller', name: 'partialPaused' }, - 'controller-get-pause-guardian': { contract: 'Controller', name: 'pauseGuardian' }, - 'l1-gateway-l2-grt': { contract: 'L1GraphTokenGateway', name: 'l2GRT' }, - 'l1-gateway-inbox': { contract: 'L1GraphTokenGateway', name: 'inbox' }, - 'l1-gateway-escrow': { contract: 'L1GraphTokenGateway', name: 'escrow' }, - 'l1-gateway-l1-router': { contract: 'L1GraphTokenGateway', name: 'l1Router' }, - 'l1-gateway-l2-counterpart': { contract: 'L1GraphTokenGateway', name: 'l2Counterpart' }, - 'l1-gateway-paused': { contract: 'L1GraphTokenGateway', name: 'paused' }, - 'l2-gateway-l1-grt': { contract: 'L2GraphTokenGateway', name: 'l1GRT' }, - 'l2-gateway-l2-router': { contract: 'L2GraphTokenGateway', name: 'l2Router' }, - 'l2-gateway-l1-counterpart': { contract: 'L2GraphTokenGateway', name: 'l1Counterpart' }, - 'l2-gateway-paused': { contract: 'L2GraphTokenGateway', name: 'paused' }, - 'l2-token-gateway': { contract: 'L2GraphToken', name: 'gateway' }, - 'l2-token-l1-address': { contract: 'L2GraphToken', name: 'l1Address' }, -} - -const buildHelp = () => { - let help = '$0 protocol get [params]\n\nGraph protocol configuration\n\nCommands:\n\n' - for (const entry of Object.keys(gettersList)) { - help += ' $0 protocol get ' + entry + ' [params]\n' - } - return help -} - -export const getProtocolParam = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - logger.info(`Getting ${cliArgs.fn}...`) - - const fn: ProtocolFunction = gettersList[cliArgs.fn] - if (!fn) { - logger.error(`Command ${cliArgs.fn} does not exist`) - return - } - - const addressEntry = cli.addressBook.getEntry(fn.contract) - - // Parse params - const params = cliArgs.params ? cliArgs.params.toString().split(',') : [] - - // Send tx - const contract = getContractAt(fn.contract, addressEntry.address).connect(cli.wallet) - const contractFn: ContractFunction = contract.functions[fn.name] - - const [value] = await contractFn(...params) - logger.info(`${fn.name} = ${value}`) -} - -export const getCommand = { - command: 'get [params]', - describe: 'Get network parameter', - builder: (yargs: Argv): yargs.Argv => { - return yargs.usage(buildHelp()) - }, - handler: async (argv: CLIArgs): Promise => { - return getProtocolParam(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/protocol/index.ts b/packages/contracts/cli/commands/protocol/index.ts deleted file mode 100644 index acab2be90..000000000 --- a/packages/contracts/cli/commands/protocol/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { listCommand } from './list' -import { getCommand } from './get' -import { setCommand } from './set' -import { configureL1BridgeCommand, configureL2BridgeCommand } from './configure-bridge' - -export interface ProtocolFunction { - contract: string - name: string -} - -// TODO: print help with fn signature -// TODO: list address-book -// TODO: add gas price - -export const protocolCommand = { - command: 'protocol', - describe: 'Graph protocol configuration', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .command(getCommand) - .command(setCommand) - .command(listCommand) - .command(configureL1BridgeCommand) - .command(configureL2BridgeCommand) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/protocol/list.ts b/packages/contracts/cli/commands/protocol/list.ts deleted file mode 100644 index c82ca1d81..000000000 --- a/packages/contracts/cli/commands/protocol/list.ts +++ /dev/null @@ -1,88 +0,0 @@ -import Table from 'cli-table' - -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { logger } from '../../logging' -import { ContractFunction } from 'ethers' - -import { gettersList } from './get' - -const contractNames = [ - 'Controller', - 'GraphToken', - 'EpochManager', - 'Staking', - 'Curation', - 'DisputeManager', - 'RewardsManager', - 'GNS', - 'L1GraphTokenGateway', - 'L2GraphToken', - 'L2GraphTokenGateway', -] - -export const listProtocolParams = async (cli: CLIEnvironment): Promise => { - logger.info(`>>> Protocol Configuration <<<\n`) - - for (const contractName of contractNames) { - const table = new Table({ - head: [contractName, 'Value'], - colWidths: [30, 50], - }) - - if (!(contractName in cli.contracts)) { - continue - } - const contract = cli.contracts[contractName] - table.push(['* address', contract.address]) - - const req = [] - for (const fn of Object.values(gettersList)) { - if (fn.contract != contractName) continue - const contract = cli.contracts[fn.contract] - if (contract.interface.getFunction(fn.name).inputs.length == 0) { - const contractFn: ContractFunction = contract.functions[fn.name] - req.push( - contractFn().then((values) => { - let [value] = values - if (typeof value === 'object') { - value = value.toString() - } - table.push([fn.name, value]) - }), - ) - } - } - await Promise.all(req) - logger.info(table.toString()) - } - - // Verify controllers - logger.info(`\n>>> Contracts Controller <<<\n`) - - const controller = cli.contracts['Controller'] - for (const contractName of contractNames) { - if (contractName === 'Controller' || !(contractName in cli.contracts)) continue - - const contract = cli.contracts[contractName] - const contractFn = contract.functions['controller'] - - if (contractFn) { - const addr = await contractFn().then((values) => values[0]) - if (addr === controller.address) { - logger.info(contractName) - } else { - logger.error(`${contractName} : ${addr} should be ${controller.address}`) - } - } else { - logger.info(contractName) - } - } -} - -export const listCommand = { - command: 'list', - describe: 'List protocol parameters', - handler: async (argv: CLIArgs): Promise => { - return listProtocolParams(await loadEnv(argv)) - }, -} diff --git a/packages/contracts/cli/commands/protocol/set.ts b/packages/contracts/cli/commands/protocol/set.ts deleted file mode 100644 index d9a2a4892..000000000 --- a/packages/contracts/cli/commands/protocol/set.ts +++ /dev/null @@ -1,130 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { logger } from '../../logging' -import { getContractAt, sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' - -import { ProtocolFunction } from './index' -import { BigNumber } from 'ethers' - -export const settersList = { - // Staking - 'staking-slasher': { contract: 'Staking', name: 'setSlasher' }, - 'staking-thawing-period': { contract: 'Staking', name: 'setThawingPeriod' }, - 'staking-max-allocation-epochs': { contract: 'Staking', name: 'setMaxAllocationEpochs' }, - 'staking-protocol-percentage': { contract: 'Staking', name: 'setProtocolPercentage' }, - 'staking-delegation-parameters': { contract: 'Staking', name: 'setDelegationParameters' }, - 'staking-delegation-unbonding-period': { - contract: 'Staking', - name: 'setDelegationUnbondingPeriod', - }, - // Curation - 'curation-reserve-ratio': { contract: 'Curation', name: 'setDefaultReserveRatio' }, - 'curation-percentage': { contract: 'Staking', name: 'setCurationPercentage' }, - 'curation-minimum-deposit': { contract: 'Curation', name: 'setMinimumCurationDeposit' }, - 'curation-tax-percentage': { contract: 'Curation', name: 'setCurationTaxPercentage' }, - // Disputes - 'disputes-arbitrator': { contract: 'DisputeManager', name: 'setArbitrator' }, - 'disputes-minimum-deposit': { contract: 'DisputeManager', name: 'setMinimumDeposit' }, - 'disputes-reward-percentage': { - contract: 'DisputeManager', - name: 'setFishermanRewardPercentage', - }, - 'disputes-slashing-percentage': { contract: 'DisputeManager', name: 'setSlashingPercentage' }, - // Epochs - 'epochs-length': { contract: 'EpochManager', name: 'setEpochLength' }, - // Rewards - 'rewards-issuance-per-block': { contract: 'RewardsManager', name: 'setIssuancePerBlock' }, - 'subgraph-availability-oracle': { - contract: 'RewardsManager', - name: 'setSubgraphAvailabilityOracle', - }, - // GNS - 'gns-owner-tax-percentage': { contract: 'GNS', name: 'setOwnerTaxPercentage' }, - // Token - 'token-transfer-governor': { contract: 'GraphToken', name: 'transferOwnership' }, - 'token-accept-governor': { contract: 'GraphToken', name: 'acceptOwnership' }, - 'token-add-minter': { contract: 'GraphToken', name: 'addMinter' }, - 'token-remove-minter': { contract: 'GraphToken', name: 'removeMinter' }, - 'token-mint': { contract: 'GraphToken', name: 'mint' }, - // Controller - 'controller-transfer-governor': { contract: 'Controller', name: 'transferOwnership' }, - 'controller-accept-governor': { contract: 'Controller', name: 'acceptOwnership' }, - 'controller-set-contract-proxy': { contract: 'Controller', name: 'setContractProxy' }, - 'controller-set-paused': { contract: 'Controller', name: 'setPaused' }, - 'controller-set-partial-paused': { contract: 'Controller', name: 'setPartialPaused' }, - 'controller-set-pause-guardian': { contract: 'Controller', name: 'setPauseGuardian' }, - 'l1-gateway-set-l2-grt': { contract: 'L1GraphTokenGateway', name: 'setL2TokenAddress' }, - 'l1-gateway-set-arbitrum-addresses': { - contract: 'L1GraphTokenGateway', - name: 'setArbitrumAddresses', - }, - 'l1-gateway-set-l2-counterpart': { - contract: 'L1GraphTokenGateway', - name: 'setL2CounterpartAddress', - }, - 'l1-gateway-set-escrow-address': { - contract: 'L1GraphTokenGateway', - name: 'setEscrowAddress', - }, - 'l1-gateway-set-paused': { contract: 'L1GraphTokenGateway', name: 'setPaused' }, - 'bridge-escrow-approve-all': { contract: 'BridgeEscrow', name: 'approveAll' }, - 'bridge-escrow-revoke-all': { contract: 'BridgeEscrow', name: 'revokeAll' }, - 'l2-gateway-set-l1-grt': { contract: 'L2GraphTokenGateway', name: 'setL1TokenAddress' }, - 'l2-gateway-set-l2-router': { contract: 'L2GraphTokenGateway', name: 'setL2Router' }, - 'l2-gateway-set-l1-counterpart': { - contract: 'L2GraphTokenGateway', - name: 'setL1CounterpartAddress', - }, - 'l2-gateway-set-paused': { contract: 'L2GraphTokenGateway', name: 'setPaused' }, - 'l2-token-set-gateway': { contract: 'L2GraphToken', name: 'setGateway' }, - 'l2-token-set-l1-address': { contract: 'L2GraphToken', name: 'setL1Address' }, -} - -const buildHelp = () => { - let help = '$0 protocol set \n\nGraph protocol configuration\n\nCommands:\n\n' - for (const entry of Object.keys(settersList)) { - help += ' $0 protocol set ' + entry + ' \n' - } - return help -} - -export const setProtocolParam = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - logger.info(`Setting ${cliArgs.fn}...`) - - const fn: ProtocolFunction = settersList[cliArgs.fn] - if (!fn) { - logger.error(`Command ${cliArgs.fn} does not exist`) - return - } - - const addressEntry = cli.addressBook.getEntry(fn.contract) - - // Parse params - const params = cliArgs.params.toString().split(',') - const parsedParams = [] - for (const param of params) { - try { - const parsedParam = BigNumber.from(param) - parsedParams.push(parsedParam.toNumber()) - } catch { - parsedParams.push(param) - } - } - logger.info(`params: ${parsedParams}`) - - // Send tx - const contract = getContractAt(fn.contract, addressEntry.address).connect(cli.wallet) - await sendTransaction(cli.wallet, contract, fn.name, parsedParams) -} - -export const setCommand = { - command: 'set ', - describe: 'Set protocol parameter', - builder: (yargs: Argv): yargs.Argv => { - return yargs.usage(buildHelp()) - }, - handler: async (argv: CLIArgs): Promise => { - return setProtocolParam(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/proxy/admin.ts b/packages/contracts/cli/commands/proxy/admin.ts deleted file mode 100644 index ad9bfafa7..000000000 --- a/packages/contracts/cli/commands/proxy/admin.ts +++ /dev/null @@ -1,70 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { logger } from '../../logging' -import { getContractAt, sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { confirm } from '../../helpers' - -export const setProxyAdmin = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const contractName = cliArgs.contract - const adminAddress = cliArgs.admin - const skipConfirmation = cliArgs.skipConfirmation - - logger.info(`Set proxy admin for contract ${contractName} to ${adminAddress}`) - - // Warn about changing ownership - const sure = await confirm(`Are you sure to set the admin to ${adminAddress}?`, skipConfirmation) - if (!sure) return - - // Get address book info - const addressEntry = cli.addressBook.getEntry(contractName) - const savedAddress = addressEntry && addressEntry.address - - if (!savedAddress) { - logger.error(`Contract ${contractName} not found in address book`) - return - } - - // Only work with addresses deployed with a proxy - if (!addressEntry.proxy) { - logger.error(`Contract ${contractName} was not deployed using a proxy`) - return - } - - // Get the proxy admin - const proxyAdminEntry = cli.addressBook.getEntry('GraphProxyAdmin') - if (!proxyAdminEntry || !proxyAdminEntry.address) { - logger.crit('Missing GraphProxyAdmin configuration') - return - } - const proxyAdmin = getContractAt('GraphProxyAdmin', proxyAdminEntry.address).connect(cli.wallet) - - // Change proxy admin - await sendTransaction(cli.wallet, proxyAdmin, 'changeProxyAdmin', [ - addressEntry.address, - adminAddress, - ]) - logger.info('Done') -} - -export const setAdminCommand = { - command: 'set-admin', - describe: 'Set proxy admin', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('admin', { - description: 'Address of the new admin', - type: 'string', - requiresArg: true, - }) - .option('contract', { - description: 'Contract name to set admin', - type: 'string', - requiresArg: true, - }) - .demandOption(['admin', 'contract']) - }, - handler: async (argv: CLIArgs): Promise => { - return setProxyAdmin(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/commands/proxy/index.ts b/packages/contracts/cli/commands/proxy/index.ts deleted file mode 100644 index 99dfc18d2..000000000 --- a/packages/contracts/cli/commands/proxy/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { setAdminCommand } from './admin' -import { listCommand } from './list' -import { upgradeCommand } from './upgrade' - -export const proxyCommand = { - command: 'proxy', - describe: 'Manage proxy contracts', - builder: (yargs: Argv): yargs.Argv => { - return yargs.command(listCommand).command(upgradeCommand).command(setAdminCommand) - }, - handler: (): void => { - yargs.showHelp() - }, -} diff --git a/packages/contracts/cli/commands/proxy/list.ts b/packages/contracts/cli/commands/proxy/list.ts deleted file mode 100644 index f20ae59ae..000000000 --- a/packages/contracts/cli/commands/proxy/list.ts +++ /dev/null @@ -1,45 +0,0 @@ -import Table from 'cli-table' - -import { logger } from '../../logging' -import { getContractAt } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' - -export const listProxies = async (cli: CLIEnvironment): Promise => { - logger.info(`Listing proxies...`) - const table = new Table({ - head: ['Contract', 'Proxy', 'Implementation', 'Admin'], - colWidths: [20, 45, 45, 45], - }) - - // Get the proxy admin - const proxyAdminEntry = cli.addressBook.getEntry('GraphProxyAdmin') - if (!proxyAdminEntry || !proxyAdminEntry.address) { - logger.crit('Missing GraphProxyAdmin configuration') - return - } - const proxyAdmin = getContractAt('GraphProxyAdmin', proxyAdminEntry.address).connect(cli.wallet) - - // Scan every proxy and get current admin and implementation - for (const contractName of cli.addressBook.listEntries()) { - const addressEntry = cli.addressBook.getEntry(contractName) - if (addressEntry.proxy) { - try { - const implementationAddress = await proxyAdmin.getProxyImplementation(addressEntry.address) - const adminAddress = await proxyAdmin.getProxyAdmin(addressEntry.address) - table.push([contractName, addressEntry.address, implementationAddress, adminAddress]) - } catch { - table.push([contractName, addressEntry.address, '', '']) - } - } - } - - logger.info(table.toString()) -} - -export const listCommand = { - command: 'list', - describe: 'List deployed proxies', - handler: async (argv: CLIArgs): Promise => { - return listProxies(await loadEnv(argv)) - }, -} diff --git a/packages/contracts/cli/commands/proxy/upgrade.ts b/packages/contracts/cli/commands/proxy/upgrade.ts deleted file mode 100644 index cdf417394..000000000 --- a/packages/contracts/cli/commands/proxy/upgrade.ts +++ /dev/null @@ -1,169 +0,0 @@ -import yargs, { Argv } from 'yargs' - -import { logger } from '../../logging' -import { getContractAt, isContractDeployed, sendTransaction } from '../../network' -import { loadEnv, CLIArgs, CLIEnvironment } from '../../env' -import { confirm } from '../../helpers' - -export const upgradeProxy = async (cli: CLIEnvironment, cliArgs: CLIArgs): Promise => { - const contractName = cliArgs.contract - const implAddress = cliArgs.impl - const initArgs = cliArgs.init - const buildAcceptProxyTx = cliArgs.buildTx - const skipConfirmation = cliArgs.skipConfirmation - - // Warn about upgrade - const sure = await confirm( - `Are you sure you want to upgrade ${contractName} to ${implAddress}?`, - skipConfirmation, - ) - if (!sure) return - - logger.info(`Upgrading contract ${contractName}...`) - - // Get address book info - const addressEntry = cli.addressBook.getEntry(contractName) - const savedAddress = addressEntry && addressEntry.address - - if (!savedAddress) { - logger.error(`Contract ${contractName} not found in address book`) - return - } - - // Only work with addresses deployed with a proxy - if (!addressEntry.proxy) { - logger.error(`Contract ${contractName} was not deployed using a proxy`) - return - } - - // Check if contract already deployed - const isDeployed = await isContractDeployed( - contractName, - savedAddress, - cli.addressBook, - cli.wallet.provider, - false, - ) - if (!isDeployed) { - logger.error( - `Proxy for ${contractName} was not deployed, please run migrate to deploy all contracts`, - ) - return - } - - // Get the proxy admin - const proxyAdminEntry = cli.addressBook.getEntry('GraphProxyAdmin') - if (!proxyAdminEntry || !proxyAdminEntry.address) { - logger.crit('Missing GraphProxyAdmin configuration') - return - } - const proxyAdmin = getContractAt('GraphProxyAdmin', proxyAdminEntry.address).connect(cli.wallet) - - // Get the current proxy and the new implementation contract - const proxy = getContractAt('GraphProxy', addressEntry.address).connect(cli.wallet) - const contract = getContractAt(contractName, implAddress).connect(cli.wallet) - - // Check if implementation already set - const currentImpl = await proxyAdmin.getProxyImplementation(proxy.address) - if (currentImpl === implAddress) { - logger.error( - `Contract ${implAddress} is already the current implementation for proxy ${proxy.address}`, - ) - return - } - - // Upgrade to new implementation - if (buildAcceptProxyTx) { - logger.info( - ` - Copy this data in the gnosis multisig UI, or a similar app and call upgrade() - You must call upgrade() BEFORE calling acceptProxy() - - contract address: ${proxyAdmin.address} - proxy: ${proxy.address} - implementation: ${implAddress} - `, - ) - if (initArgs) { - const initTx = await contract.populateTransaction.initialize(...initArgs.split(',')) - logger.info( - ` - Copy this data in the gnosis multisig UI, or a similar app and call acceptProxyAndCall() - - contract address: ${proxyAdmin.address} - implementation: ${contract.address} - proxy: ${proxy.address} - data: ${initTx.data} - `, - ) - } else { - logger.info( - ` - Copy this data in the gnosis multisig UI, or a similar app and call acceptProxy() - - contract address: ${proxyAdmin.address} - implementation: ${contract.address} - proxy: ${proxy.address} - `, - ) - } - } else { - const receipt = await sendTransaction(cli.wallet, proxyAdmin, 'upgrade', [ - proxy.address, - implAddress, - ]) - if (receipt.status == 1) { - logger.info('> upgrade() tx successful!') - } else { - logger.info('> upgrade() tx failed!') - return - } - - // Accept upgrade from the implementation - if (initArgs) { - const initTx = await contract.populateTransaction.initialize(...initArgs.split(',')) - await sendTransaction(cli.wallet, proxyAdmin, 'acceptProxyAndCall', [ - implAddress, - proxy.address, - initTx.data, - ]) - } else { - await sendTransaction(cli.wallet, proxyAdmin, 'acceptProxy', [implAddress, proxy.address]) - } - } - - // TODO - // -- update address book entry -} - -export const upgradeCommand = { - command: 'upgrade', - describe: 'Upgrade a proxy contract implementation', - builder: (yargs: Argv): yargs.Argv => { - return yargs - .option('impl', { - description: 'Address of the contract implementation', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('init', { - description: 'Init arguments as comma-separated values', - type: 'string', - requiresArg: true, - }) - .option('contract', { - description: 'Contract name to upgrade', - type: 'string', - requiresArg: true, - demandOption: true, - }) - .option('b', { - alias: 'build-tx', - description: 'Build the acceptProxy tx and print it. Then use tx data with a multisig', - }) - }, - handler: async (argv: CLIArgs): Promise => { - return upgradeProxy(await loadEnv(argv), argv) - }, -} diff --git a/packages/contracts/cli/config.ts b/packages/contracts/cli/config.ts deleted file mode 100644 index cc2a4e966..000000000 --- a/packages/contracts/cli/config.ts +++ /dev/null @@ -1,161 +0,0 @@ -import fs from 'fs' -import YAML from 'yaml' -import { Scalar, YAMLMap } from 'yaml/types' - -import { AddressBook } from './address-book' -import { CLIEnvironment } from './env' - -const ABRefMatcher = /\${{([A-Z]\w.+)}}/ - -type ContractParam = { name: string; value: string } -type ContractCall = { fn: string; params: Array } -type ContractCallParam = string | number -interface ContractConfig { - params: Array - calls: Array - proxy: boolean -} - -function parseConfigValue(value: string, addressBook: AddressBook, cli: CLIEnvironment) { - if (isAddressBookRef(value)) { - return parseAddressBookRef(addressBook, value, cli) - } - return value -} - -function isAddressBookRef(value: string): boolean { - return ABRefMatcher.test(value) -} - -function parseAddressBookRef(addressBook: AddressBook, value: string, cli: CLIEnvironment): string { - const ref: string = ABRefMatcher.exec(value as string)[1] - const [contractName, contractAttr] = ref.split('.') - // This is a convention to use the inject CLI-env variables into the config - if (contractName === 'Env') { - if (contractAttr == 'deployer') { - return cli.walletAddress - } - throw new Error('Attribute not found in the CLI env') - } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const entry = addressBook.getEntry(contractName) as { [key: string]: any } - return entry[contractAttr] -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function readConfig(path: string, retainMetadata = false): any { - const file = fs.readFileSync(path, 'utf8') - return retainMetadata ? YAML.parseDocument(file) : YAML.parse(file) -} - -export function writeConfig(path: string, data: string): void { - fs.writeFileSync(path, data) -} - -export function loadCallParams( - values: Array, - addressBook: AddressBook, - cli: CLIEnvironment, -): Array { - return values.map((value) => parseConfigValue(value as string, addressBook, cli)) -} - -export function getContractConfig( - config: any, - addressBook: AddressBook, - name: string, - cli: CLIEnvironment, -): ContractConfig { - const contractConfig = config.contracts[name] || {} - const contractParams: Array = [] - const contractCalls: Array = [] - let proxy = false - - const optsList = Object.entries(contractConfig) as Array> - for (const [name, value] of optsList) { - // Process constructor params - if (name.startsWith('init')) { - const initList = Object.entries(contractConfig.init) as Array> - for (const [initName, initValue] of initList) { - // This allows passing structs as constructor params - // We can't however inject CLI env variables into struct params - const value = - typeof initValue === 'object' - ? Object.values(initValue) - : parseConfigValue(initValue, addressBook, cli) - - contractParams.push({ - name: initName, - value: value, - } as { - name: string - value: string - }) - } - continue - } - - // Process contract calls - if (name.startsWith('calls')) { - for (const entry of contractConfig.calls) { - const fn = entry['fn'] - const params = Object.values(entry).slice(1) as Array // skip fn - contractCalls.push({ fn, params }) - } - continue - } - - // Process proxy - if (name.startsWith('proxy')) { - proxy = Boolean(value) - continue - } - } - - return { - params: contractParams, - calls: contractCalls, - proxy, - } -} - -// YAML helper functions -const getNode = (doc: YAML.Document.Parsed, path: string[]): YAMLMap => { - try { - let node: YAMLMap - for (const p of path) { - node = node === undefined ? doc.get(p) : node.get(p) - } - return node - } catch (error) { - throw new Error(`Could not find node: ${path}.`) - } -} - -function getItem(node: YAMLMap, key: string): Scalar { - if (!node.has(key)) { - throw new Error(`Could not find item: ${key}.`) - } - return node.get(key, true) as Scalar -} - -function getItemFromPath(doc: YAML.Document.Parsed, path: string) { - const splitPath = path.split('/') - const itemKey = splitPath.pop() - - const node = getNode(doc, splitPath) - const item = getItem(node, itemKey) - return item -} - -export const getItemValue = (doc: YAML.Document.Parsed, path: string): any => { - const item = getItemFromPath(doc, path) - return item.value -} - -export const updateItemValue = (doc: YAML.Document.Parsed, path: string, value: any): boolean => { - const item = getItemFromPath(doc, path) - const updated = item.value !== value - item.value = value - return updated -} diff --git a/packages/contracts/cli/contracts.ts b/packages/contracts/cli/contracts.ts deleted file mode 100644 index 0c8da1b91..000000000 --- a/packages/contracts/cli/contracts.ts +++ /dev/null @@ -1,220 +0,0 @@ -import { - BaseContract, - Contract, - ContractFunction, - ContractReceipt, - ContractTransaction, - providers, - Signer, -} from 'ethers' -import { Provider } from '@ethersproject/providers' -import lodash from 'lodash' -import fs from 'fs' - -import { AddressBook } from './address-book' -import { chainIdIsL2 } from './cross-chain' -import { logger } from './logging' -import { getContractAt } from './network' - -import { EpochManager } from '../build/types/EpochManager' -import { DisputeManager } from '../build/types/DisputeManager' -import { L1Staking } from '../build/types/L1Staking' -import { L2Staking } from '../build/types/L2Staking' -import { ServiceRegistry } from '../build/types/ServiceRegistry' -import { Curation } from '../build/types/Curation' -import { RewardsManager } from '../build/types/RewardsManager' -import { GNS } from '../build/types/GNS' -import { L1GNS } from '../build/types/L1GNS' -import { L2GNS } from '../build/types/L2GNS' -import { GraphProxyAdmin } from '../build/types/GraphProxyAdmin' -import { GraphToken } from '../build/types/GraphToken' -import { Controller } from '../build/types/Controller' -import { BancorFormula } from '../build/types/BancorFormula' -import { IENS } from '../build/types/IENS' -import { GraphGovernance } from '../build/types/GraphGovernance' -import { AllocationExchange } from '../build/types/AllocationExchange' -import { SubgraphNFT } from '../build/types/SubgraphNFT' -import { GraphCurationToken } from '../build/types/GraphCurationToken' -import { SubgraphNFTDescriptor } from '../build/types/SubgraphNFTDescriptor' -import { L1GraphTokenGateway } from '../build/types/L1GraphTokenGateway' -import { L2GraphToken } from '../build/types/L2GraphToken' -import { L2GraphTokenGateway } from '../build/types/L2GraphTokenGateway' -import { BridgeEscrow } from '../build/types/BridgeEscrow' -import { L2Curation } from '../build/types/L2Curation' -import { IL1Staking } from '../build/types/IL1Staking' -import { IL2Staking } from '../build/types/IL2Staking' -import { Interface } from 'ethers/lib/utils' -import { loadArtifact } from './artifacts' - -export interface NetworkContracts { - EpochManager: EpochManager - DisputeManager: DisputeManager - Staking: IL1Staking | IL2Staking - ServiceRegistry: ServiceRegistry - Curation: Curation | L2Curation - L2Curation: L2Curation - RewardsManager: RewardsManager - GNS: GNS | L1GNS | L2GNS - GraphProxyAdmin: GraphProxyAdmin - GraphToken: GraphToken - Controller: Controller - BancorFormula: BancorFormula - IENS: IENS - GraphGovernance: GraphGovernance - AllocationExchange: AllocationExchange - SubgraphNFT: SubgraphNFT - SubgraphNFTDescriptor: SubgraphNFTDescriptor - GraphCurationToken: GraphCurationToken - L1GraphTokenGateway: L1GraphTokenGateway - BridgeEscrow: BridgeEscrow - L2GraphToken: L2GraphToken - L2GraphTokenGateway: L2GraphTokenGateway - L1GNS: L1GNS - L2GNS: L2GNS - L1Staking: IL1Staking - L2Staking: IL2Staking -} - -export const loadAddressBookContract = ( - contractName: string, - addressBook: AddressBook, - signerOrProvider?: Signer | providers.Provider, -): BaseContract => { - const contractEntry = addressBook.getEntry(contractName) - let contract = getContractAt(contractName, contractEntry.address) - if (signerOrProvider) { - contract = contract.connect(signerOrProvider) - } - return contract -} - -export const loadContracts = ( - addressBook: AddressBook, - chainId: number | string, - signerOrProvider?: Signer | providers.Provider, - enableTXLogging = false, -): NetworkContracts => { - const contracts = {} - for (const contractName of addressBook.listEntries()) { - const contractEntry = addressBook.getEntry(contractName) - - try { - let contract = getContractAt(contractName, contractEntry.address) - if (enableTXLogging) { - contract.connect = getWrappedConnect(contract, contractName) - contract = wrapCalls(contract, contractName) - } - if (contractName == 'L1Staking') { - // Hack the contract into behaving like an IL1Staking - const iface = new Interface(loadArtifact('IL1Staking').abi) - contract = new Contract(contract.address, iface) as unknown as IL1Staking - } else if (contractName == 'L2Staking') { - // Hack the contract into behaving like an IL2Staking - const iface = new Interface(loadArtifact('IL2Staking').abi) - contract = new Contract(contract.address, iface) as unknown as IL2Staking - } - contracts[contractName] = contract - - if (signerOrProvider) { - contracts[contractName] = contracts[contractName].connect(signerOrProvider) - } - - // On L2 networks, we alias L2GraphToken as GraphToken - if (chainIdIsL2(chainId) && contractName == 'L2GraphToken') { - contracts['GraphToken'] = contracts[contractName] - } - if (signerOrProvider && chainIdIsL2(chainId) && contractName == 'L2GNS') { - contracts['GNS'] = contracts[contractName] - } - if (signerOrProvider && chainIdIsL2(chainId) && contractName == 'L2Staking') { - contracts['Staking'] = contracts[contractName] - } - if (signerOrProvider && chainIdIsL2(chainId) && contractName == 'L2Curation') { - contracts['Curation'] = contracts[contractName] - } - if (signerOrProvider && !chainIdIsL2(chainId) && contractName == 'L1GNS') { - contracts['GNS'] = contracts[contractName] - } - if (signerOrProvider && !chainIdIsL2(chainId) && contractName == 'L1Staking') { - contracts['Staking'] = contracts[contractName] - } - } catch (err) { - logger.warn(`Could not load contract ${contractName} - ${err.message}`) - } - } - return contracts as NetworkContracts -} - -// Returns a contract connect function that wrapps contract calls with wrapCalls -function getWrappedConnect( - contract: Contract, - contractName: string, -): (signerOrProvider: string | Provider | Signer) => Contract { - const call = contract.connect.bind(contract) - const override = (signerOrProvider: string | Provider | Signer): Contract => { - const connectedContract = call(signerOrProvider) - connectedContract.connect = getWrappedConnect(connectedContract, contractName) - return wrapCalls(connectedContract, contractName) - } - return override -} - -// Returns a contract with wrapped calls -// The wrapper will run the tx, wait for confirmation and log the details -function wrapCalls(contract: Contract, contractName: string): Contract { - const wrappedContract = lodash.cloneDeep(contract) - - for (const fn of Object.keys(contract.functions)) { - const call: ContractFunction = contract.functions[fn] - const override = async (...args: Array): Promise => { - // Make the call - const tx = await call(...args) - logContractCall(tx, contractName, fn, args) - - // Wait for confirmation - const receipt = await contract.provider.waitForTransaction(tx.hash) - logContractReceipt(tx, receipt) - return tx - } - - wrappedContract.functions[fn] = override - wrappedContract[fn] = override - } - - return wrappedContract -} - -function logContractCall( - tx: ContractTransaction, - contractName: string, - fn: string, - args: Array, -) { - const msg = [] - msg.push(`> Sent transaction ${contractName}.${fn}`) - msg.push(` sender: ${tx.from}`) - msg.push(` contract: ${tx.to}`) - msg.push(` params: [ ${args} ]`) - msg.push(` txHash: ${tx.hash}`) - - logToConsoleAndFile(msg) -} - -function logContractReceipt(tx: ContractTransaction, receipt: ContractReceipt) { - const msg = [] - msg.push( - receipt.status ? `✔ Transaction succeeded: ${tx.hash}` : `✖ Transaction failed: ${tx.hash}`, - ) - - logToConsoleAndFile(msg) -} - -function logToConsoleAndFile(msg: string[]) { - const isoDate = new Date().toISOString() - const fileName = `tx-${isoDate.substring(0, 10)}.log` - - msg.map((line) => { - console.log(line) - fs.appendFileSync(fileName, `[${isoDate}] ${line}\n`) - }) -} diff --git a/packages/contracts/cli/cross-chain.ts b/packages/contracts/cli/cross-chain.ts deleted file mode 100644 index 870d572b4..000000000 --- a/packages/contracts/cli/cross-chain.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { L1ToL2MessageGasEstimator } from '@arbitrum/sdk' -import { L1ToL2MessageNoGasParams } from '@arbitrum/sdk/dist/lib/message/L1ToL2MessageCreator' -import { GasOverrides } from '@arbitrum/sdk/dist/lib/message/L1ToL2MessageGasEstimator' -import { BigNumber, providers } from 'ethers' -import { parseEther } from 'ethers/lib/utils' - -import { logger } from './logging' - -export const l1ToL2ChainIdMap = { - '1': '42161', - '4': '421611', - '5': '421613', - '1337': '412346', - '11155111': '421614', -} - -export const l2ChainIds = Object.values(l1ToL2ChainIdMap).map(Number) -export const l2ToL1ChainIdMap = Object.fromEntries( - Object.entries(l1ToL2ChainIdMap).map(([k, v]) => [v, k]), -) - -export const chainIdIsL2 = (chainId: number | string): boolean => { - return l2ChainIds.includes(Number(chainId)) -} - -interface L2GasParams { - maxGas: BigNumber - gasPriceBid: BigNumber - maxSubmissionCost: BigNumber -} - -export const estimateRetryableTxGas = async ( - l1Provider: providers.Provider, - l2Provider: providers.Provider, - gatewayAddress: string, - l2Dest: string, - depositCalldata: string, - opts: L2GasParams, -): Promise => { - const autoEstimate = opts && (!opts.maxGas || !opts.gasPriceBid || !opts.maxSubmissionCost) - if (!autoEstimate) { - return opts - } - - // Comment from Offchain Labs' implementation: - // we add a 0.05 ether "deposit" buffer to pay for execution in the gas estimation - logger.info('Estimating retryable ticket gas:') - const baseFee = (await l1Provider.getBlock('latest')).baseFeePerGas - const gasEstimator = new L1ToL2MessageGasEstimator(l2Provider) - const retryableEstimateData: L1ToL2MessageNoGasParams = { - from: gatewayAddress, - to: l2Dest, - data: depositCalldata, - l2CallValue: parseEther('0'), - excessFeeRefundAddress: gatewayAddress, - callValueRefundAddress: gatewayAddress, - } - - const estimateOpts: GasOverrides = {} - if (opts.maxGas) estimateOpts.gasLimit = { base: opts.maxGas } - if (opts.maxSubmissionCost) estimateOpts.maxSubmissionFee = { base: opts.maxSubmissionCost } - if (opts.gasPriceBid) estimateOpts.maxFeePerGas = { base: opts.gasPriceBid } - - const gasParams = await gasEstimator.estimateAll( - retryableEstimateData, - baseFee as BigNumber, - l1Provider, - estimateOpts, - ) - - // override fixed values - return { - maxGas: opts.maxGas ?? gasParams.gasLimit, - gasPriceBid: opts.gasPriceBid ?? gasParams.maxFeePerGas, - maxSubmissionCost: opts.maxSubmissionCost ?? gasParams.maxSubmissionCost, - } -} diff --git a/packages/contracts/cli/defaults.ts b/packages/contracts/cli/defaults.ts deleted file mode 100644 index e7ac22f3f..000000000 --- a/packages/contracts/cli/defaults.ts +++ /dev/null @@ -1,81 +0,0 @@ -import { Options } from 'yargs' -import { Overrides } from 'ethers' - -export const local = { - mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', - providerUrl: 'http://localhost:8545', - addressBookPath: './addresses-local.json', - graphConfigPath: './config/graph.mainnet.yml', - accountNumber: '0', - arbitrumAddressBookPath: './arbitrum-addresses.json', - arbProviderUrl: 'https://rinkeby.arbitrum.io/rpc', -} - -export const defaultOverrides: Overrides = { - // gasPrice: utils.parseUnits('25', 'gwei'), // auto - // gasLimit: 2000000, // auto -} - -export const cliOpts = { - addressBook: { - alias: 'address-book', - description: 'The path to your address book file', - type: 'string', - group: 'Config', - default: local.addressBookPath, - }, - graphConfig: { - alias: 'graph-config', - description: 'The path to the config file', - type: 'string', - group: 'Config', - default: local.graphConfigPath, - }, - providerUrl: { - alias: 'provider-url', - description: 'The URL of an Ethereum provider', - type: 'string', - group: 'Ethereum', - default: local.providerUrl, - }, - mnemonic: { - alias: 'mnemonic', - description: 'The mnemonic for an account which will pay for gas', - type: 'string', - group: 'Ethereum', - default: local.mnemonic, - }, - accountNumber: { - alias: 'account-number', - description: 'The account number of the mnemonic', - type: 'string', - group: 'Ethereum', - default: local.accountNumber, - }, - force: { - alias: 'force', - description: "Deploy contract even if it's already deployed", - type: 'boolean', - default: false, - }, - skipConfirmation: { - alias: 'skip-confirmation', - description: 'Skip confirmation prompt on write actions', - type: 'boolean', - default: false, - }, - arbitrumAddressBook: { - alias: 'arb-address-book', - description: 'The path to the address book file for Arbitrum deployments', - type: 'string', - group: 'Config', - default: local.arbitrumAddressBookPath, - }, - l2ProviderUrl: { - alias: 'l2-provider-url', - description: 'The URL of an Arbitrum provider (only for bridge commands)', - type: 'string', - group: 'Arbitrum', - default: local.arbProviderUrl, - }, -} as { [key: string]: Options } diff --git a/packages/contracts/cli/env.ts b/packages/contracts/cli/env.ts deleted file mode 100644 index 0aaaecc24..000000000 --- a/packages/contracts/cli/env.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { utils, BigNumber, Wallet, Overrides } from 'ethers' -import { Argv } from 'yargs' - -import { logger } from './logging' -import { getAddressBook, AddressBook } from './address-book' -import { defaultOverrides } from './defaults' -import { getProvider } from './network' -import { loadContracts, NetworkContracts } from './contracts' - -const { formatEther } = utils - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type CLIArgs = { [key: string]: any } & Argv['argv'] - -export interface CLIEnvironment { - balance: BigNumber - chainId: number - nonce: number - walletAddress: string - wallet: Wallet - addressBook: AddressBook - contracts: NetworkContracts - argv: CLIArgs -} - -export const displayGasOverrides = (): Overrides => { - const r = { gasPrice: 'auto', gasLimit: 'auto', ...defaultOverrides } - if (r['gasPrice']) { - r['gasPrice'] = r['gasPrice'].toString() - } - return r -} - -function isMnemonic(mnemonic) { - return mnemonic.split(' ').length >= 12 && mnemonic.split(' ').length <= 24 -} - -function isPrivateKey(privateKey) { - try { - utils.getAddress(utils.computeAddress(privateKey)) - return true - } catch (error) { - return false - } -} - -export const loadEnv = async (argv: CLIArgs, wallet?: Wallet): Promise => { - if (!wallet) { - if (isPrivateKey(argv.mnemonic)) { - wallet = new Wallet(argv.mnemonic, getProvider(argv.providerUrl)) - } else if (isMnemonic(argv.mnemonic)) { - wallet = Wallet.fromMnemonic(argv.mnemonic, `m/44'/60'/0'/0/${argv.accountNumber}`).connect( - getProvider(argv.providerUrl), - ) - } else { - throw new Error( - 'A wallet was not provided, please complete the `mnemonic` argument with a valid value', - ) - } - } - - const balance = await wallet.getBalance() - const chainId = (await wallet.provider.getNetwork()).chainId - const nonce = await wallet.getTransactionCount() - const walletAddress = await wallet.getAddress() - const addressBook = getAddressBook(argv.addressBook, chainId.toString()) - const contracts = loadContracts(addressBook, chainId, wallet) - - logger.info(`Preparing contracts on chain id: ${chainId}`) - logger.info( - `Connected Wallet: address=${walletAddress} nonce=${nonce} balance=${formatEther(balance)}\n`, - ) - logger.info(`Gas settings: ${JSON.stringify(displayGasOverrides())}`) - - return { - balance, - chainId, - nonce, - walletAddress, - wallet, - addressBook, - contracts, - argv, - } -} diff --git a/packages/contracts/cli/helpers.ts b/packages/contracts/cli/helpers.ts deleted file mode 100644 index 115336eca..000000000 --- a/packages/contracts/cli/helpers.ts +++ /dev/null @@ -1,133 +0,0 @@ -import fs from 'fs' -import path from 'path' -import * as dotenv from 'dotenv' - -import { utils, BigNumber, BigNumberish, Signer } from 'ethers' -import ipfsHttpClient from 'ipfs-http-client' -import inquirer from 'inquirer' - -import * as bs58 from 'bs58' - -import { logger } from './logging' - -import { - SubgraphMetadata, - VersionMetadata, - jsonToSubgraphMetadata, - jsonToVersionMetadata, -} from './metadata' -import { solidityKeccak256 } from 'ethers/lib/utils' -import { GraphToken } from '../build/types/GraphToken' - -dotenv.config() - -export class IPFS { - static createIpfsClient(node: string): typeof ipfsHttpClient { - let url: URL - try { - url = new URL(node) - } catch (e) { - throw new Error( - `Invalid IPFS URL: ${node}. ` + - `The URL must be of the following format: http(s)://host[:port]/[path]`, - ) - } - - return ipfsHttpClient({ - protocol: url.protocol.replace(/[:]+$/, ''), - host: url.hostname, - 'api-path': url.pathname.replace(/\/$/, '') + '/api/v0/', - }) - } - - static ipfsHashToBytes32(hash: string): string { - const hashBytes = bs58.decode(hash).slice(2) - return utils.hexlify(hashBytes) - } -} - -export const pinMetadataToIPFS = async ( - ipfs: string, - type: string, - filepath?: string, // Only pass path or metadata, not both - metadata?: SubgraphMetadata | VersionMetadata, -): Promise => { - if (metadata == undefined && filepath != undefined) { - if (type == 'subgraph') { - metadata = jsonToSubgraphMetadata( - JSON.parse(fs.readFileSync(path.join(__dirname, filepath)).toString()), - ) - logger.info('Meta data:') - logger.info(` Subgraph Description: ${metadata.description}`) - logger.info(`Subgraph Display Name: ${metadata.displayName}`) - logger.info(` Subgraph Image: ${metadata.image}`) - logger.info(` Subgraph Code Repository: ${metadata.codeRepository}`) - logger.info(` Subgraph Website: ${metadata.website}`) - } else if (type == 'version') { - metadata = jsonToVersionMetadata( - JSON.parse(fs.readFileSync(path.join(__dirname, filepath)).toString()), - ) - logger.info('Meta data:') - logger.info(` Version Description: ${metadata.description}`) - logger.info(` Version Label: ${metadata.label}`) - } - } - - const ipfsClient = new ipfsHttpClient(ipfs + 'api/v0') - let result - logger.info(`\nUpload JSON meta data for ${type} to IPFS...`) - try { - result = await ipfsClient.add(Buffer.from(JSON.stringify(metadata))) - } catch (e) { - logger.error(`Failed to upload to IPFS: ${e}`) - return - } - - const metaHash = result.path - - // TODO - maybe add this back in. ipfs-http-client was updated, so it broke - // try { - // const data = await ipfsClient.cat(metaHash) - // if (JSON.stringify(data) !== JSON.stringify(metadata)) { - // throw new Error(`Original meta data and uploaded data are not identical`) - // } - // } catch (e) { - // throw new Error(`Failed to retrieve and parse JSON meta data after uploading: ${e.message}`) - // } - logger.info(`Upload metadata successful: ${metaHash}\n`) - return IPFS.ipfsHashToBytes32(metaHash) -} - -export const confirm = async (message: string, skip: boolean): Promise => { - if (skip) return true - const res = await inquirer.prompt({ - name: 'confirm', - type: 'confirm', - message, - }) - if (!res.confirm) { - logger.info('Cancelled') - return false - } - return true -} - -export const buildSubgraphID = (account: string, seqID: BigNumber): string => - solidityKeccak256(['address', 'uint256'], [account, seqID]) - -export const ensureGRTAllowance = async ( - owner: Signer, - spender: string, - amount: BigNumberish, - grt: GraphToken, -): Promise => { - const ownerAddress = await owner.getAddress() - const allowance = await grt.allowance(ownerAddress, spender) - const allowTokens = BigNumber.from(amount).sub(allowance) - if (allowTokens.gt(0)) { - console.log( - `\nApproving ${spender} to spend ${allowTokens} tokens on ${ownerAddress} behalf...`, - ) - await grt.connect(owner).approve(spender, amount) - } -} diff --git a/packages/contracts/cli/index.ts b/packages/contracts/cli/index.ts deleted file mode 100644 index 66eb53068..000000000 --- a/packages/contracts/cli/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import * as network from './network' - -export { network } diff --git a/packages/contracts/cli/logging.ts b/packages/contracts/cli/logging.ts deleted file mode 100644 index 40bb65784..000000000 --- a/packages/contracts/cli/logging.ts +++ /dev/null @@ -1,18 +0,0 @@ -import winston, { format } from 'winston' - -// const fullFormatter = format.combine( -// format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), -// format.colorize(), -// format.printf( -// ({ level, message, label, timestamp }) => `${timestamp} ${label || '-'} ${level}: ${message}`, -// ), -// ) - -export const logger: winston.Logger = winston.createLogger({ - level: 'info', - format: format.combine( - format.colorize(), - format.printf(({ message }) => `${message}`), - ), - transports: [new winston.transports.Console({ level: 'info' })], -}) diff --git a/packages/contracts/cli/metadata.ts b/packages/contracts/cli/metadata.ts deleted file mode 100644 index 96b74068c..000000000 --- a/packages/contracts/cli/metadata.ts +++ /dev/null @@ -1,68 +0,0 @@ -interface AccountMetadata { - codeRepository: string - description: string - image: string - name: string - website: string - displayName -} - -interface SubgraphMetadata { - description: string - displayName: string - image: string - codeRepository: string - website: string -} - -interface VersionMetadata { - label: string - description: string -} - -const jsonToSubgraphMetadata = (json): SubgraphMetadata => { - const subgraphMetadata: SubgraphMetadata = { - description: checkString(json.description), - displayName: checkString(json.displayName), - image: checkString(json.image), - codeRepository: checkString(json.codeRepository), - website: checkString(json.website), - } - return subgraphMetadata -} - -const jsonToVersionMetadata = (json): VersionMetadata => { - const subgraphMetadata: VersionMetadata = { - label: checkString(json.label), - description: checkString(json.description), - } - return subgraphMetadata -} - -const jsonToAccountMetadata = (json): AccountMetadata => { - const accountMetadata: AccountMetadata = { - codeRepository: checkString(json.codeRepository), - description: checkString(json.description), - image: checkString(json.image), - name: checkString(json.name), - website: checkString(json.website), - displayName: checkString(json.displayName), - } - return accountMetadata -} - -const checkString = (field): string => { - if (typeof field != 'string') { - throw Error('Metadata field is incorrect for one or more files') - } - return field -} - -export { - AccountMetadata, - SubgraphMetadata, - VersionMetadata, - jsonToSubgraphMetadata, - jsonToVersionMetadata, - jsonToAccountMetadata, -} diff --git a/packages/contracts/cli/mockData/account-metadata/accountMetadatas.ts b/packages/contracts/cli/mockData/account-metadata/accountMetadatas.ts deleted file mode 100644 index 8567a1c38..000000000 --- a/packages/contracts/cli/mockData/account-metadata/accountMetadatas.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { jsonToAccountMetadata } from '../metadataHelpers' - -import compound from './compound.json' -import decentraland from './decentraland.json' -import ens from './ens.json' -import livepeer from './livepeer.json' -import maker from './maker.json' -import melon from './melon.json' -import moloch from './moloch.json' -import origin from './origin.json' -import thegraph from './thegraph.json' -import uniswap from './uniswap.json' - -const compoundAccountMetadata = jsonToAccountMetadata(compound) -const decentralandAccountMetadata = jsonToAccountMetadata(decentraland) -const ensAccountMetadata = jsonToAccountMetadata(ens) -const livepeerAccountMetadata = jsonToAccountMetadata(livepeer) -const makerAccountMetadata = jsonToAccountMetadata(maker) -const melonAccountMetadata = jsonToAccountMetadata(melon) -const molochAccountMetadata = jsonToAccountMetadata(moloch) -const originAccountMetadata = jsonToAccountMetadata(origin) -const thegraphAccountMetadata = jsonToAccountMetadata(thegraph) -const uniswapAccountMetadata = jsonToAccountMetadata(uniswap) - -export default { - compoundAccountMetadata, - decentralandAccountMetadata, - ensAccountMetadata, - livepeerAccountMetadata, - makerAccountMetadata, - melonAccountMetadata, - molochAccountMetadata, - originAccountMetadata, - thegraphAccountMetadata, - uniswapAccountMetadata, -} diff --git a/packages/contracts/cli/mockData/account-metadata/compound.json b/packages/contracts/cli/mockData/account-metadata/compound.json deleted file mode 100644 index 30836a0e3..000000000 --- a/packages/contracts/cli/mockData/account-metadata/compound.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/compound-finance", - "description": "Compound developer", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Compound developer", - "website": "https://compound.finance", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/decentraland.json b/packages/contracts/cli/mockData/account-metadata/decentraland.json deleted file mode 100644 index 147013455..000000000 --- a/packages/contracts/cli/mockData/account-metadata/decentraland.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/Decentraland", - "description": "Decentraland developer", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Decentraland developer", - "website": "https://decentraland.io", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/ens.json b/packages/contracts/cli/mockData/account-metadata/ens.json deleted file mode 100644 index d8019e116..000000000 --- a/packages/contracts/cli/mockData/account-metadata/ens.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/ensdomains", - "description": "ENS developer", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "ENS developer", - "website": "https://ens.domains/", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/livepeer.json b/packages/contracts/cli/mockData/account-metadata/livepeer.json deleted file mode 100644 index aafa6dfe9..000000000 --- a/packages/contracts/cli/mockData/account-metadata/livepeer.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/adam", - "description": "Adam", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Adam", - "website": "https://adam.com/", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/maker.json b/packages/contracts/cli/mockData/account-metadata/maker.json deleted file mode 100644 index f23f16c6f..000000000 --- a/packages/contracts/cli/mockData/account-metadata/maker.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/makerdao", - "description": "Maker dev", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Maker deve", - "website": "https://maker.io/", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/melon.json b/packages/contracts/cli/mockData/account-metadata/melon.json deleted file mode 100644 index b0f7adeda..000000000 --- a/packages/contracts/cli/mockData/account-metadata/melon.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/melon", - "description": "Melon developer", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Melon developer", - "website": "https://melon.finance/", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/moloch.json b/packages/contracts/cli/mockData/account-metadata/moloch.json deleted file mode 100644 index 49ffd3dc2..000000000 --- a/packages/contracts/cli/mockData/account-metadata/moloch.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/molochcrypto", - "description": "Moloch dev", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Moloch dev", - "website": "https://moloch.io/", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/origin.json b/packages/contracts/cli/mockData/account-metadata/origin.json deleted file mode 100644 index 2828b009b..000000000 --- a/packages/contracts/cli/mockData/account-metadata/origin.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/origin-dev", - "description": "Origin dev", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Origin dev", - "website": "https://origin-dev.io", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/thegraph.json b/packages/contracts/cli/mockData/account-metadata/thegraph.json deleted file mode 100644 index e968e0e9f..000000000 --- a/packages/contracts/cli/mockData/account-metadata/thegraph.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/davekaj", - "description": "Dave Kajpusts graph account", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Dave Kajpust", - "website": "https://kajpust.com/", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/account-metadata/uniswap.json b/packages/contracts/cli/mockData/account-metadata/uniswap.json deleted file mode 100644 index 59b261d08..000000000 --- a/packages/contracts/cli/mockData/account-metadata/uniswap.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "codeRepository": "github.com/ian", - "description": "Ian", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQyA3o9G72wcAKfGhQSFkspCLMRXUtyidxNCc4tJjCwTW", - "name": "Ian", - "website": "https://ian.com", - "isOrganization": true -} diff --git a/packages/contracts/cli/mockData/bulkPhaseData/phase1-signalling.csv b/packages/contracts/cli/mockData/bulkPhaseData/phase1-signalling.csv deleted file mode 100644 index 4d3d26c9a..000000000 --- a/packages/contracts/cli/mockData/bulkPhaseData/phase1-signalling.csv +++ /dev/null @@ -1,17 +0,0 @@ -displayName,description,subgraphID,signal,codeRepository,image,website -Uniswap V2,Uniswap V2,QmWTrJJ9W8h3JE19FhCzzPYsJ2tgXZCdUqnbyuo64ToTBN,"1000000",https://github.com/uniswap/uniswap-v2-subgraph,https://api.thegraph.com/ipfs/api/v0/cat?arg=QmWQn64mrw9eVBfau2TxknR8bQNs4BkCy7mUi9UaZG9ofs, -Synthetix Rates,Synthetix Rates,QmdbHP5ALcHda6UdCtZLYEwQJo7xTKKgUXMwMLLiCspYFE,"1000000",https://github.com/Synthetixio/synthetix-subgraph,https://storage.googleapis.com/subgraph-images/1599682669782SNX%20(2).png, -Balancer,Balancer,QmXorTXBbcJ9YHH8YKjdz5KxVENz43fdXxciFHZHvi8m6c,"900000",https://github.com/balancer-labs/balancer-subgraph,https://storage.googleapis.com/subgraph-images/1582850720988pebbles-padcircle-white.256w.png, -Curve,Curve,QmNs5fU6VkyGUsaNsa5sUHEKpzCA5AZWKJG8LaBrcCRpmW,"900000",,https://storage.googleapis.com/subgraph-images/default/sg-4.png, -UMA,UMA,QmdJjt7nX7bZraGLRb93eJMQ9ND4SwoFQtA934N3FdxMBs,"800000",https://github.com/protofire/uma-subgraph ,https://storage.googleapis.com/subgraph-images/1594053638802910-uma-project.png, -Aave,Aave,QmU3qzWocSGuywhLonGiYmv22XS5sHatfEBp3vrJrRGdD6,"800000",https://github.com/aave/aave-protocol/tree/master/thegraph,https://storage.googleapis.com/subgraph-images/1578403270665sticker_aave_telegram.png, -Mintbase,Mintbase,QmW5UcMhXwXrMqRpTdT3MKB7HYDxbsp5oe9Atkuh4sgAA5,"800000",https://github.com/Mintbase/graph-mint-factory,https://storage.googleapis.com/subgraph-images/1573754371189logo-solo-white.png, -Known Origin,Known Origin,QmUxpVrcmXRmJgi8CMXu8JPHABspnoaewQjDujc17bkGqR,"800000",https://github.com/knownorigin/known-origin-subgraph ,https://storage.googleapis.com/subgraph-images/1575098880182440px_LogoIcn.png, -Opyn,Opyn,QmNVmy3hA6JVqZfMGoQc68GsB9GzGiEVLjhR1pHLY2xwuS,"700000",,https://storage.googleapis.com/subgraph-images/1581473209487Opyn2.png, -Protocol Multy Raw,Protocol Multy Raw,QmaTCNvS72s7gULbrnKE9D4WaDA3HBD7yXUA9d2wGJUXHQ,"600000",https://github.com/graphprotocol/aave-protocol,https://storage.googleapis.com/subgraph-images/1590485690460sticker_aave_telegram.png, -Keeper DAO,Keeper DAO,QmW6BrjSMPUSjMApTNYZShHi9XShgziC5YppGvqyjjAAX1,"500000",,https://storage.googleapis.com/subgraph-images/default/sg-2.png, -Token Sets,Token Sets,QmZ6noN8Ek4dPpyvmSv4AdAtefVWtUsopBc8hFKFiWo1Uw,"500000",https://github.com/GraphiteTools/tokensets-subgraph ,https://storage.googleapis.com/subgraph-images/1586498344313tokensets.png, -Synthetix Exchanges,Synthetix Exchanges,QmNmLRx82a8FEvVr3aBahEReAj3fN4JSmHG2ufTEVwVR7z,"450000",https://github.com/Synthetixio/synthetix-subgraph,https://storage.googleapis.com/subgraph-images/1569869352912Slack___jordan___Synthetix.jpg, -Compound,Compound,QmdYA3zCs27962HNchhcjJbyfT3hZtLhANJuo1BsMv5YTs,"400000",https://github.com/GraphiteTools/compound-subgraph ,https://storage.googleapis.com/subgraph-images/1586460211036compound.png, -MStable,MStable,QmWNP1jqMZm61G8FbsLzi9Mnii5qRXbkadBxXVHZPqzKri,"300000",https://gitlab.com/mstable/mstable-graph,https://storage.googleapis.com/subgraph-images/1586091586012mstable_logo_circle_m_black.jpg, -Tellor,Tellor,QmbBHyLRN97BssF7w6MnULW92f7iaM7vX7fnNU6wDDj3fc,"300000",,https://storage.googleapis.com/subgraph-images/default/sg-9.png, diff --git a/packages/contracts/cli/mockData/bulkPhaseData/phase1-unsignal.csv b/packages/contracts/cli/mockData/bulkPhaseData/phase1-unsignal.csv deleted file mode 100644 index 5ec780c64..000000000 --- a/packages/contracts/cli/mockData/bulkPhaseData/phase1-unsignal.csv +++ /dev/null @@ -1,19 +0,0 @@ -Account,Subgraph Number,Amount (percentage) -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,0,10 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,1,20 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,2,100 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,3,40 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,4,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,5,70 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,6,12 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,7,88 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,8,17 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,9,23 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,10,45 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,11,55 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,12,65 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,13,99 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,14,1 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,15,2 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,16,30 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,17,44 \ No newline at end of file diff --git a/packages/contracts/cli/mockData/bulkPhaseData/phase2-signalling.csv b/packages/contracts/cli/mockData/bulkPhaseData/phase2-signalling.csv deleted file mode 100644 index 6ac55752b..000000000 --- a/packages/contracts/cli/mockData/bulkPhaseData/phase2-signalling.csv +++ /dev/null @@ -1,88 +0,0 @@ -displayName,description,subgraphID,signal,codeRepository,image -Uniswap V2,historical data and analytics for Uniswap V2,QmWTrJJ9W8h3JE19FhCzzPYsJ2tgXZCdUqnbyuo64ToTBN,1010000,https://github.com/uniswap/uniswap-v2-subgraph,https://storage.googleapis.com/subgraph-images/1591820950702256x256_App_Icon_Gradient.png -Ethereum Blocks,Indexing all Ethereum Block data,QmNtTKStPBm3bnghvyKLNY5B8etER8CG9ei9m7APT1kdx6,75514,https://github.com/blocklytics/ethereum-blocks,https://storage.googleapis.com/subgraph-images/1579070275738ethereum_logo_square.png -Brightid Honey Faucet Xdai,Subgraph for BrightId Honey Faucet on xDai,QmYMUQESxrhz7UkwnshnCEbprLWQbZVPyNd3jFggS8FAtK,71722,,https://storage.googleapis.com/subgraph-images/default/sg-9.png -LINKUSD,Subgraph for LINKUSD,Qmbpwh32waJ21xgYLBw9ZV9v5ikehANXqQTaxErii7ypbT,210447,,https://storage.googleapis.com/subgraph-images/default/sg-3.png -Balancer,Generalized AMM and portfolio manager,QmbS7vmAWXJqsJEnAbvNSBYQXxCUmZWHFQygHPbyb3vy3N,58478,,https://storage.googleapis.com/subgraph-images/1582850720988pebbles-padcircle-white.256w.png -Synthetix Rates,Rate updates from Synthetix,QmPYVDfyyQ72dwr4HPG8JC1SZGvLhewMTqfDwByH6M1dPa,554340,,https://storage.googleapis.com/subgraph-images/1569418199094Pasted_Image_9_25_19__9_29_AM.jpg -SakeSwap Subgraph V2,Analytics for SakeSwap,QmcAGrSedyweWQhKCbdMUxbX2ddMiSJwWRRc3NcDtoXnDE,38619,https://github.com/therealsakeswap/sakeswap-subgraph-univ2,https://storage.googleapis.com/subgraph-images/default/sg-8.png -Opyn,Opyn Mainnet Subgraph,QmNVmy3hA6JVqZfMGoQc68GsB9GzGiEVLjhR1pHLY2xwuS,1221,https://https://github.com/aparnakr/OpynGraph,https://storage.googleapis.com/subgraph-images/1581473209487Opyn.png -Curve,Trades and liquidity details for Curve.fi DeFi platform,QmVaFg6W4vofpNSsMNVx1SNDn4n8bQm9ou95JH6FDiKqQ1,132196,,https://storage.googleapis.com/subgraph-images/default/sg-4.png -Uniswap,Uniswap is a decentralized protocol for automated token exchange on Ethereum.,QmRuorV4Ck1sVdpfpAAwfYXnf3cfSkbDwZvvzWud9SH8Dg,19564,,https://storage.googleapis.com/subgraph-images/1548114951622uniswap.png -Gringotts,Gringotts Wizarding Bank,QmPmPrNHGkWZLMuXiNf59odjxSAwMBciMNNenf9MSqyBfy,584040,,https://storage.googleapis.com/subgraph-images/1601451095309gringotts.jpg -Mintbase,All stores and those stores tokens,QmW5UcMhXwXrMqRpTdT3MKB7HYDxbsp5oe9Atkuh4sgAA5,17572,https://github.com/Mintbase/graph-mint-factory,https://storage.googleapis.com/subgraph-images/1573754371189logo-solo-white.png -Aragon Conviction Voting Xdai,Conviction voting subgraph Xdai,QmWPnuoYxQrb8Hc5MNZboRmyAqjYhV5B8ndgyHywUptcRV,1306,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -Aavegotchi Aragon,Aavegotchi Bonding Curve,QmY6Si48nCutHkofaXDL1mJd4XUxs2SCPeo4G6CT661z4P,12224,,https://storage.googleapis.com/subgraph-images/default/sg-7.png -SushiSwap Subgraph Fork,A fork of Uniswap subgraph to test things out,QmPSzSpAHozDWgqsa9FMKk2qd1xrhEZJfhGxskgz4b8HoQ,11808,,https://storage.googleapis.com/subgraph-images/default/sg-3.png -Known Origin,KnownOrigin artwork listings,QmTFeK8XKtA6hm2nZ8ectqyqTmx1ga8qiMpxQyyxfBrduv,227640,https://github.com/knownorigin/known-origin-subgraph,https://storage.googleapis.com/subgraph-images/1575098880182440px_LogoIcn.png -mStable protocol,Mint redeem and save mStable assets with this data,QmWNP1jqMZm61G8FbsLzi9Mnii5qRXbkadBxXVHZPqzKri,8821,,https://storage.googleapis.com/subgraph-images/1586091586012mstable_logo_circle_m_black.jpg -Token Sets,Crypto management made easy,QmZ6noN8Ek4dPpyvmSv4AdAtefVWtUsopBc8hFKFiWo1Uw,8002,https://github.com/Destiner/TokenSets-subgraph,https://storage.googleapis.com/subgraph-images/1569163566860TokenSets.png -UMA,UMA Subgraph,QmVviUCWpxxZuwekyHe87vspJsaugG1KDkfqEwjm3788ku,5781,https://github.com/protofire/uma-subgraph,https://storage.googleapis.com/subgraph-images/1601561900375DsMClZnT_400x400.jpg -Synthetix Exchanges,A subgraph on all exchanges in Synthetix,QmX9CNPbbYoFGvucHzNJkjTAMGKNWzUSFveWmgdoB6WVJm,5441,https://github.com/Synthetixio/synthetix-subgraph,https://storage.googleapis.com/subgraph-images/1569869352912Slack___jordan___Synthetix.jpg -Bancor V2,Bancor v2,QmbykNCTDoRx5NMgJgoXY7YARoV3xTRNfs4cWifsc3fm7u,5390,,https://storage.googleapis.com/subgraph-images/default/sg-1.png -Protocol,Aave's Protocol subgraph(legacy),QmU3qzWocSGuywhLonGiYmv22XS5sHatfEBp3vrJrRGdD6,5182,https://github.com/aave/aave-protocol/tree/master/thegraph,https://storage.googleapis.com/subgraph-images/1578403270665sticker_aave_telegram.png -Try Second Graph,mooniswap 2,QmQgmUrUKBkQfsKdNNnfcUpUxRvyrX27W4knuhn4q6GfpH,40420,,https://storage.googleapis.com/subgraph-images/default/sg-2.png -exchange,exchange,QmWpFQJWVBkzTfabZL5DxnAvdhjP5FjbBW87jP2XcjyuUb,3990,,https://storage.googleapis.com/subgraph-images/default/sg-3.png -Protocol Multy Raw,Aave protocol subgraph with all pools data,QmS8ZBEgXisX7yEm8daSQmmVkwQ6wH6WU1B4nBkYKrjHo2,3679,https://github.com/graphprotocol/aave-protocol,https://storage.googleapis.com/subgraph-images/1590485690460sticker_aave_telegram.png -Xdai Blocks,All the blocks on Xdai,QmVxQBxjdswNYNmz2ocSDknkbnCwvQLJd1onxwuHtuoumd,3338,,https://storage.googleapis.com/subgraph-images/default/sg-1.png -SushiSwap,Swap data from sushiswap,QmUmgYJL3yp7EiSgxQ3zVxmDMJn3ZXDnYZWija4BWciEvu,2930,,https://storage.googleapis.com/subgraph-images/default/sg-7.png -Marketplace,Decentraland's Marketplace,QmXdZDKnDX2o9qfupGDTXFM1xxspndHrHAGpbkWAPMs6Qk,2773,https://github.com/decentraland/marketplace,https://storage.googleapis.com/subgraph-images/1578327676983color.png -KeeperDAO,KeeperDAO,QmW6BrjSMPUSjMApTNYZShHi9XShgziC5YppGvqyjjAAX1,2546,,https://storage.googleapis.com/subgraph-images/default/sg-2.png -Multisig Mainnet,Multisig (network: Mainnet),Qmd8JSo29vQX3iP45JMVEL2zQJ6bQEMkqnWsoW3eRjMJEn,2528,,https://storage.googleapis.com/subgraph-images/default/sg-8.png -Unlock,Unlock on mainnet,QmR2uzq3Tt3htYTmefFwJ6eX2aYySY6ZRZkW9LZG39Byrh,2521,https://github.com/unlock-protocol/unlock-subgraph,https://storage.googleapis.com/subgraph-images/1569531464009unlock.png -Miniswap,MiniSwap provides a decentralised platform.,QmZ4fvpTgWCL3oQbf7uzy9bszotLTxv6pGbYfGk7VopTst,2373,,https://storage.googleapis.com/subgraph-images/1601020924950MIniswap600.png -Easy Staking,EasyStaking,QmfVC5EMxkkyh6tLt94o8Kh239WVNppDP6jLJncviCSK4k,2314,,https://storage.googleapis.com/subgraph-images/default/sg-4.png -RenVM,RenVM graph explorer,QmP595e8r4VRPcKG5bfHUSN4ybbYnZkjgYkSHjfDw5YshY,2114,https://github.com/renproject/renvm-subgraph,https://storage.googleapis.com/subgraph-images/1590115100825icon-white.png -Livepeer,A protocol for affordable and reliable video encoding.,QmaEsTQhqGfZMjHYpNxmcxU3pD4GbAU6u5F8AqePeQumYv,2067,https://github.com/livepeer/livepeerjs/tree/master/packages/subgraph,https://storage.googleapis.com/subgraph-images/1565207456060livepeer.png -Ephimera,Ephimera,QmNkNBJKGzN65UtD3PKC2zV7EeHrHtWZsRErRsxyq55xw1,2015,,https://storage.googleapis.com/subgraph-images/default/sg-9.png -thelao1,lao,QmXAkoTqZZus7qd6JJ7dycKPwYWQuBu1raPBNfhq59gaGL,1915,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -Tellor Dispute V2,tellor dispute center v2,QmfCaCcQnfBWXgCpbtf9kKWosVqUbeGLfEomYVJkMBqKj9,1601,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -KeeperDAO Staging,KeeperDAO staging environment,QmTnwP1Bs61Bpb2GNBjYBFmVreZzDx3xDowQGGC63WxsWF,1564,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -NIFTEX Uniswap Graph,NIFTEX Uniswap Pools Data,QmdoMvZbk2YDyDVQjhS73RfqymffMxz4EW1uS9RhEEfqog,1558,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -Cream Swap V2,Crypto Rules Everything Around Me C.R.E.A.M.,QmcPSRpF28QSWpgAgNPFVyiGYd75L5aSrKGLXhmaFW5bSK,1403,,https://storage.googleapis.com/subgraph-images/1602679008376CREAM_transparent_Secondary_straight_color.png -LINKUSD rinkeby,LINKUSD on Rinkeby,QmYefoMwvtKYPQVrZZRTaVeX1K2CP51Eft8E7Dt8LeCRsa,1181,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -Prod,2nd Layer Protocol Embedding Smart Contracts into HTTP Links,QmQhuSbS2J5DzbHVFNLKYqFJDS9hhLxyWys6uGZDamhPeD,1176,https://github.com/2key/2key-subgraphs,https://storage.googleapis.com/subgraph-images/15644936648972key-white-bg.gif -Flamingo NFT,Flamingo NFT (mainnet),Qma3LJSzh4q5RGS5inHMLiGCBVTQ16PnGeRJscCDcQsWkH,1163,,https://storage.googleapis.com/subgraph-images/default/sg-7.png -Stake Subgraph V2,Stake Subgraph V2,QmUEfxv9AQmn1BoAr8C56Z3oALGrEkG7V2doGjYDpVuBH5,1115,,https://storage.googleapis.com/subgraph-images/default/sg-2.png -Oneinchswapped3,Stats,QmcYkKNVBW67p9UWFMEcETWjgKqjnJ1nupPmJQoaLPW7CU,1087,,https://storage.googleapis.com/subgraph-images/default/sg-10.png -Honey Pot Xdai,Honey pot subgraph for xdai network,QmRQJBmUh1vxp184FScwLeKviNXiazbxWKRBWkeh1HXhVw,974,,https://storage.googleapis.com/subgraph-images/1601582404472bee.png -Try Graph,test,Qmd3yXPzi3cRBW8assGLHDi65s6EZagparh55fZ2FGP7Tf,943,,https://storage.googleapis.com/subgraph-images/default/sg-8.png -Sablier,Mainnet subgraph,QmamoWRdcCzkgYDXLFzxdoejzCJMvJYfdNwQorWU4B4Rtg,398000,,https://storage.googleapis.com/subgraph-images/1573584068471icon_spaced_gradient_2.png -Balancer Beta,Balancer,QmXPQBpRJ8Vjut71DyYWst8VkCbhdKCAJ9f4q3BWboXd87,765,,https://storage.googleapis.com/subgraph-images/default/sg-1.png -Circlesxdai,Circles subgraph for The Graph to fastly query available data in the Circles UBI ecosystem,QmVRkGqh7mCsZdgfMGQDLUjTYDbR6u51jWCTsG2mj8wLHf,728,,https://storage.googleapis.com/subgraph-images/16006014343575qr4Cm5q_400x400.jpg -Keeper Pool Mainnet,Keeper Pool Related Data in Mainnet Network,QmX28DCsTkd9TWLssR1YRwBr6weQ61t5VTnHimff1zZMCT,728,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -Uniswap,Subgraph to organize Uniswap transaction data,QmQ2Hm4EqUycftdZqmMftgghZ8DpsbUh3T6FHkEvBMp1Yr,136400,https://github.com/graphprotocol/uniswap-subgraph,https://storage.googleapis.com/subgraph-images/1548114951622uniswap.png -v8_12_exp_xdai,arc index xdai,QmSZ6wNaTQdCCqsfPNPrCXq9oGLKt7rRE3cHYWDjiTksjq,636,,https://storage.googleapis.com/subgraph-images/default/sg-2.png -Mint Factory,Capture all the sub contracts,QmYUdKTsNe9fDuWZMeXTAF7tKosSuokzgauHQSEUUU89B1,619,https://github.com/Mintbase/graph-mint-factory,https://storage.googleapis.com/subgraph-images/1573378599056logo-solo-white.png -Staging,2nd Layer Protocol Embedding Smart Contracts into HTTP Links,QmVivTDmJMXJXyJcjcFDV2NLqf27xMzedXmCvmFcPdFoco,573,https://github.com/2key/2key-subgraphs,https://storage.googleapis.com/subgraph-images/15644935789752Key_Logo_Final Formats-FIX_LightGreen.png -Purple Warlock Staging,A graph for the demo,QmSgYxcy6AJ41ZdvmVgdZYEU4yzeccZeCQK8QNn75X5wtL,109600,,https://storage.googleapis.com/subgraph-images/default/sg-2.png -Pollen,Pollen is a fully decentralized DAO-governed DeFi Asset Pool,QmeHPFWH8qmEBpzZRTzjEa7vajnbGQZ2SzJ8v6fkA6W9nX,541,https://github.com/PollenDeFi/pollen-subgraph,https://storage.googleapis.com/subgraph-images/1595078030985logo192.png -v39_8,arc index mainnet,QmWex7boz79MGkYmcLbjDg4N13kLsLQAtTfLyjcz6RgJ9i,475,,https://storage.googleapis.com/subgraph-images/default/sg-4.png -ENS,A secure & decentralized way to address resources on and off the blockchain using simple human-readable names. Access domains and transfer history.,QmY8Uzg61ttrogeTyCKLcDDR4gKNK44g9qkGDqeProkSHE,456,,https://storage.googleapis.com/subgraph-images/1548795052635ENS_Logo_WHITE.png -Gotchiv1,Gotchi test 1 on rinkeby,QmNVAQpyWNiHQrmvXLQSCG7PLDEUcQ9Ay3nU9j5ppTgFFU,447,,https://storage.googleapis.com/subgraph-images/default/sg-6.png -Yearn Vault ROI Dev,Development subgraph for yearn vault ROI,Qmdab4gjWa1yCACgAAcWjab2c16oqmPo6j5WtZjZ21UxcZ,9614,,https://storage.googleapis.com/subgraph-images/default/sg-5.png -Pooltogether,Records data for PoolTogether,QmecFPxMeFeHETwJdrivTNecBTCko5nyRGgidRrVp4BSfc,437,https://github.com/pooltogether/pooltogether-subgraph,https://storage.googleapis.com/subgraph-images/1599758845172pooltogether-purple-mark@2x.png -Cream Swap Beta,Crypto Rules Everything Around Me C.R.E.A.M.,QmREAAZS5ZB5nAABCutPRVBGVgaVHz21e1miwWXnpGZm51,404,https://github.com/CreamFi/balancer-subgraph,https://storage.googleapis.com/subgraph-images/1599400535254CREAM_transparent_Secondary_straight_color.png -mStable Governance,mStable Governance Subgraph,QmdXYzFaj3nqURSpx7jWvkiYnzVaMobTnQfXzPYYjnYLqv,396,,https://storage.googleapis.com/subgraph-images/1599839414747mta.png -Develop,2nd Layer Protocol Embedding Smart Contracts into HTTP Links,QmafKiDwT7EBJYL9y3rdfnBFUWzkGNytoGzUsiJAxePnLm,383,https://github.com/2key/2key-subgraphs,https://storage.googleapis.com/subgraph-images/15644929968952key_logo_final_formats-fixv2_samlil_1_copy_3__1___2_.png -ptf vesting,PTF Vesting,QmdTVBZyFKcRQRHW7U8ph9Mt4oDBvBrD679FxWQQGiUoJF,356,,https://storage.googleapis.com/subgraph-images/1600677311813Bull BW.png -Uniswap,Uniswap data importer for Unspent.io,QmRpG1kMLJxnruvCScfs4JYPeHJEnJk1ZsEdhpfqaGPUHs,351,,https://storage.googleapis.com/subgraph-images/default/sg-6.png -F8N XDai,Subgraph for xDai,QmYnxSNW9iDPNvHQyP5HZsMsn7chXeKKY7yaQ1uSBvyx28,347,,https://storage.googleapis.com/subgraph-images/default/sg-10.png -Mooniswap,stat for mooniswap,QmUBFkuoDzxHx2EPxwGQdBwshqTF79fzKQnXjTRNVHwg6e,26,,https://storage.googleapis.com/subgraph-images/default/sg-4.png -Circles,Subgraph for Circles community currency,QmcyT4SWn7ctMsm1avAV3jnmCL7u3ZK93XrxcJJJt7hUF5,340,https://github.com/CirclesUBI/circles-subgraph/,https://storage.googleapis.com/subgraph-images/1595251875896circleslogo.jpg -AirSwap,Trading history indexers delegates and more.,QmZ28XHpz1BNhR5jU2ABCqo2PqHutAPE8woaW1tYdDFDqV,51150,https://github.com/airswap/airswap-protocols,https://storage.googleapis.com/subgraph-images/158680119781426823563.png -protocol,Gnosis Protocol,QmQrapV3GN6GnkMByUbf6Xrw1xVqSNAbQtNkXsy6xKAs15,328,https://github.com/gnosis/dex-subgraph,https://storage.googleapis.com/subgraph-images/1585926751418Gnosis_protocol_2019_logo_all_rgb_orange.png -Swap Subgraph,Swap Subgraph for Crypto.com DeFi,QmXhAzDVyYnxSLaeLGDpN941WJ3tyatqhyxh9ScwM82cgJ,325,,https://storage.googleapis.com/subgraph-images/default/sg-6.png -chapter2,To Assist Uniswap2,QmXRD5WZYtVERWkTpFvmqWGkpbbQ1KmsLUgCiRckkNmSJp,302,https://github.com/???,https://storage.googleapis.com/subgraph-images/1601209694793test.jpg -Protocol Raw,Aave protocol data in small units,QmNQz8mhUnkAcfDDEuKZaVdBwffZtYfoUtbQ9NYpaSS1QH,275,https://github.com/aave/aave-protocol/tree/master/thegraph,https://storage.googleapis.com/subgraph-images/1579854627676sticker_aave_telegram.png -Aragon Voting Mainnet,Subgraph for Aragon Connect Voting,QmZ92X4yhsjb7hnttAQMHeG1mH9C2SbLmiSGirHpU74iLW,233,https://github.com/aragon/connect,https://storage.googleapis.com/subgraph-images/1591893467064aralogo1.png -Nifty Ink,A subgraph for nifty.ink (in development),QmS8beCgmU8JLgXCTn7jxkCRtZ5p5mirh1Npcuk7RrBmNJ,226,,https://storage.googleapis.com/subgraph-images/1600381719322party-dinosaur.gif -Nifty Ink Main,Mainnet Nifty Ink Subgraph,Qma7vTnYU9V5FuZhAgwo9zw289KAD8mh4JKMMtMZP8nSVT,222,,https://storage.googleapis.com/subgraph-images/default/sg-7.png -Protocol Multy Kovan Raw,Aave protocol subgraph with all pools data,QmPrz3AMvEJR5dbaxHWvDawJQBFWYRTuSHp5rdrQowSayj,219,https://github.com/graphprotocol/aave-protocol,https://storage.googleapis.com/subgraph-images/1590485671765sticker_aave_telegram.png -Curve VotingEscrow Mainnet,Curve VotingEscrow Mainnet subgraph,QmXwR6LiGaP9yYTsSq8wGUS91Bqat7dStDsuH2XSoeKctY,213,,https://storage.googleapis.com/subgraph-images/default/sg-9.png -Chapter3,Miniswap mainnet channel,QmYPh4BHfJRszYBP7tnPFPHpKf2DdyHAtgRbE8PAnU1fZN,20100,https://github.com/???,https://storage.googleapis.com/subgraph-images/1601393873317zz.jpg -LAND Manager,LAND permissions with a timestamp,QmZWZWLQqY7FqsjjTsShheSZDSmj1Q3RLogNSwME3yep4Q,200,https://github.com/nicosantangelo/watchtower,https://storage.googleapis.com/subgraph-images/1590095332591dlc.png -Always For Sale Gallery,Always for sale art gallery,QmWNcVnVeLHW2QzbUvgEycYdPCNEict1Kd7n9p8ywNPTqD,187,,https://storage.googleapis.com/subgraph-images/default/sg-4.png -NexusMutualTVL,tvl for nexus mutual,QmSErYUZkNj4jy7vVYAZikPdXnbjWS3kW1GWZ9Ff29bKSU,186,,https://storage.googleapis.com/subgraph-images/default/sg-2.png -mStable protocol ropsten,A subgraph for mStable's testnet,QmPNCGkzNffdimLqmchcf7EdT5UwwDjkVcUpgwivkt8RtH,184,,https://storage.googleapis.com/subgraph-images/1590589045486mstable_logo_circle_m_black.jpg -Compound V2,A protocol for algorithmic efficient Money Markets.,QmTN6gMCBCYTgbis33eSvr6sLsQoQ3R6a2KzR7CqmMABQP,182000,,https://storage.googleapis.com/subgraph-images/1573145149921compound.png \ No newline at end of file diff --git a/packages/contracts/cli/mockData/bulkPhaseData/phase2.2-signaling.csv b/packages/contracts/cli/mockData/bulkPhaseData/phase2.2-signaling.csv deleted file mode 100644 index c7952beda..000000000 --- a/packages/contracts/cli/mockData/bulkPhaseData/phase2.2-signaling.csv +++ /dev/null @@ -1,66 +0,0 @@ -displayName,description,subgraphID,signal,codeRepository,image,website -Uniswap V2,historical data and analytics for Uniswap V2,QmWTrJJ9W8h3JE19FhCzzPYsJ2tgXZCdUqnbyuo64ToTBN,22149244,https://github.com/uniswap/uniswap-v2-subgraph,https://storage.googleapis.com/subgraph-images/1591820950702256x256_App_Icon_Gradient.png, -Ethereum Blocks,Indexing all Ethereum Block data,QmNtTKStPBm3bnghvyKLNY5B8etER8CG9ei9m7APT1kdx6,22149244,https://github.com/blocklytics/ethereum-blocks,https://storage.googleapis.com/subgraph-images/1579070275738ethereum_logo_square.png, -LINKUSD,Subgraph for LINKUSD,Qmbpwh32waJ21xgYLBw9ZV9v5ikehANXqQTaxErii7ypbT,41529833,,https://storage.googleapis.com/subgraph-images/default/sg-3.png, -Synthetix Rates,Rate updates from Synthetix,QmPYVDfyyQ72dwr4HPG8JC1SZGvLhewMTqfDwByH6M1dPa,27686555,,https://storage.googleapis.com/subgraph-images/1569418199094Pasted_Image_9_25_19__9_29_AM.jpg, -SakeSwap Subgraph V2,Analytics for SakeSwap,QmcAGrSedyweWQhKCbdMUxbX2ddMiSJwWRRc3NcDtoXnDE,11074622,https://github.com/therealsakeswap/sakeswap-subgraph-univ2,https://storage.googleapis.com/subgraph-images/default/sg-8.png, -Balancer,Generalized AMM and portfolio manager,QmbS7vmAWXJqsJEnAbvNSBYQXxCUmZWHFQygHPbyb3vy3N,41529833,,https://storage.googleapis.com/subgraph-images/1582850720988pebbles-padcircle-white.256w.png, -Gringotts,Gringotts Wizarding Bank,QmPmPrNHGkWZLMuXiNf59odjxSAwMBciMNNenf9MSqyBfy,3599252,,https://storage.googleapis.com/subgraph-images/1601451095309gringotts.jpg, -SushiSwap Subgraph Fork,A fork of Uniswap subgraph to test things out,QmPSzSpAHozDWgqsa9FMKk2qd1xrhEZJfhGxskgz4b8HoQ,276865,,https://storage.googleapis.com/subgraph-images/default/sg-3.png, -Token Sets,Crypto management made easy,QmZ6noN8Ek4dPpyvmSv4AdAtefVWtUsopBc8hFKFiWo1Uw,6921638,https://github.com/Destiner/TokenSets-subgraph,https://storage.googleapis.com/subgraph-images/1569163566860TokenSets.png, -Mstable,Stable coin protocol,QmWNP1jqMZm61G8FbsLzi9Mnii5qRXbkadBxXVHZPqzKri,16611933,,, -Mintbase,All stores and those stores tokens,QmW5UcMhXwXrMqRpTdT3MKB7HYDxbsp5oe9Atkuh4sgAA5,6921638,https://github.com/Mintbase/graph-mint-factory,https://storage.googleapis.com/subgraph-images/1573754371189logo-solo-white.png, -Bancor V2,Bancor v2,QmbykNCTDoRx5NMgJgoXY7YARoV3xTRNfs4cWifsc3fm7u,276865,,https://storage.googleapis.com/subgraph-images/default/sg-1.png, -Uniswap V2,Uniswap V2 - lutter,QmXKwSEMirgWVn41nRzkT3hpUBw29cp619Gx58XW6mPhZP,2768655,,, -Livepeer,A protocol for affordable and reliable video encoding.,QmaEsTQhqGfZMjHYpNxmcxU3pD4GbAU6u5F8AqePeQumYv,4152983,https://github.com/livepeer/livepeerjs/tree/master/packages/subgraph,https://storage.googleapis.com/subgraph-images/1565207456060livepeer.png, -NIFTEX Uniswap Graph,NIFTEX Uniswap Pools Data,QmdoMvZbk2YDyDVQjhS73RfqymffMxz4EW1uS9RhEEfqog,2768655,,https://storage.googleapis.com/subgraph-images/default/sg-5.png, -RenVM,RenVM graph explorer,QmP595e8r4VRPcKG5bfHUSN4ybbYnZkjgYkSHjfDw5YshY,2768655,https://github.com/renproject/renvm-subgraph,https://storage.googleapis.com/subgraph-images/1590115100825icon-white.png, -Miniswap,MiniSwap provides a decentralised platform.,QmZ4fvpTgWCL3oQbf7uzy9bszotLTxv6pGbYfGk7VopTst,2768655,,https://storage.googleapis.com/subgraph-images/1601020924950MIniswap600.png, -Flamingo NFT,Flamingo NFT (mainnet),Qma3LJSzh4q5RGS5inHMLiGCBVTQ16PnGeRJscCDcQsWkH,2768655,,https://storage.googleapis.com/subgraph-images/default/sg-7.png, -Uniswap,Uniswap is a decentralized protocol for automated token exchange on Ethereum.,QmRuorV4Ck1sVdpfpAAwfYXnf3cfSkbDwZvvzWud9SH8Dg,1384327,,https://storage.googleapis.com/subgraph-images/1548114951622uniswap.png, -Try Second Graph,mooniswap 2,QmQgmUrUKBkQfsKdNNnfcUpUxRvyrX27W4knuhn4q6GfpH,1384327,,https://storage.googleapis.com/subgraph-images/default/sg-2.png, -Oneinchswapped3,Stats,QmcYkKNVBW67p9UWFMEcETWjgKqjnJ1nupPmJQoaLPW7CU,1384327,,https://storage.googleapis.com/subgraph-images/default/sg-10.png, -Cream Swap V2,"Crypto Rules Everything Around Me C.R.E.A.M.",QmcPSRpF28QSWpgAgNPFVyiGYd75L5aSrKGLXhmaFW5bSK,1384327,,https://storage.googleapis.com/subgraph-images/1602679008376CREAM_transparent_Secondary_straight_color.png, -Easy Staking,EasyStaking,QmfVC5EMxkkyh6tLt94o8Kh239WVNppDP6jLJncviCSK4k,1384327,,https://storage.googleapis.com/subgraph-images/default/sg-4.png, -Try Graph,test,Qmd3yXPzi3cRBW8assGLHDi65s6EZagparh55fZ2FGP7Tf,1384327,,https://storage.googleapis.com/subgraph-images/default/sg-8.png, -Sablier,Mainnet subgraph,QmamoWRdcCzkgYDXLFzxdoejzCJMvJYfdNwQorWU4B4Rtg,1938058,,https://storage.googleapis.com/subgraph-images/1573584068471icon_spaced_gradient_2.png, -Keeper Pool Mainnet,Keeper Pool Related Data in Mainnet Network,QmX28DCsTkd9TWLssR1YRwBr6weQ61t5VTnHimff1zZMCT,1107462,,https://storage.googleapis.com/subgraph-images/default/sg-5.png, -Prod,2nd Layer Protocol Embedding Smart Contracts into HTTP Links,QmQhuSbS2J5DzbHVFNLKYqFJDS9hhLxyWys6uGZDamhPeD,1661193,https://github.com/2key/2key-subgraphs,https://storage.googleapis.com/subgraph-images/15644936648972key-white-bg.gif, -exchange,exchange,QmWpFQJWVBkzTfabZL5DxnAvdhjP5FjbBW87jP2XcjyuUb,1107462,,https://storage.googleapis.com/subgraph-images/default/sg-3.png, -Pooltogether,Records data for PoolTogether,QmecFPxMeFeHETwJdrivTNecBTCko5nyRGgidRrVp4BSfc,1107462,https://github.com/pooltogether/pooltogether-subgraph,https://storage.googleapis.com/subgraph-images/1599758845172pooltogether-purple-mark@2x.png, -SushiSwap,Swap data from sushiswap,QmUmgYJL3yp7EiSgxQ3zVxmDMJn3ZXDnYZWija4BWciEvu,830596,,https://storage.googleapis.com/subgraph-images/default/sg-7.png, -Aave Protocol,Aave's Protocol subgraph(legacy),QmU3qzWocSGuywhLonGiYmv22XS5sHatfEBp3vrJrRGdD6,830596,https://github.com/aave/aave-protocol/tree/master/thegraph,https://storage.googleapis.com/subgraph-images/1578403270665sticker_aave_telegram.png, -KeeperDAO Staging,KeeperDAO staging environment,QmTnwP1Bs61Bpb2GNBjYBFmVreZzDx3xDowQGGC63WxsWF,830596,,https://storage.googleapis.com/subgraph-images/default/sg-5.png, -Balancer Beta,Balancer,QmXPQBpRJ8Vjut71DyYWst8VkCbhdKCAJ9f4q3BWboXd87,553731,,https://storage.googleapis.com/subgraph-images/default/sg-1.png, -KeeperDAO,KeeperDAO,QmW6BrjSMPUSjMApTNYZShHi9XShgziC5YppGvqyjjAAX1,553731,,https://storage.googleapis.com/subgraph-images/default/sg-2.png, -Aave Protocol Raw,Aave protocol data in small units,QmNQz8mhUnkAcfDDEuKZaVdBwffZtYfoUtbQ9NYpaSS1QH,692163,https://github.com/aave/aave-protocol/tree/master/thegraph,https://storage.googleapis.com/subgraph-images/1579854627676sticker_aave_telegram.png, -NexusMutualTVL,tvl for nexus mutual,QmSErYUZkNj4jy7vVYAZikPdXnbjWS3kW1GWZ9Ff29bKSU,553731,,https://storage.googleapis.com/subgraph-images/default/sg-2.png, -Uniswap,Subgraph to organize Uniswap transaction data,QmQ2Hm4EqUycftdZqmMftgghZ8DpsbUh3T6FHkEvBMp1Yr,553731,https://github.com/graphprotocol/uniswap-subgraph,https://storage.googleapis.com/subgraph-images/1548114951622uniswap.png, -Curve VotingEscrow Mainnet,Curve VotingEscrow Mainnet subgraph,QmXwR6LiGaP9yYTsSq8wGUS91Bqat7dStDsuH2XSoeKctY,276865,,https://storage.googleapis.com/subgraph-images/default/sg-9.png, -Nifty Ink Main,Mainnet Nifty Ink Subgraph,Qma7vTnYU9V5FuZhAgwo9zw289KAD8mh4JKMMtMZP8nSVT,553731,,https://storage.googleapis.com/subgraph-images/default/sg-7.png, -Aave protocol multi-raw,Aave raw subgraph,QmU2AuSzxAWQfZ8dxvAbyZ9kGf87DPinxeJRHPY4JTvbTf,276865,,, -Chapter3,Miniswap mainnet channel,QmYPh4BHfJRszYBP7tnPFPHpKf2DdyHAtgRbE8PAnU1fZN,276865,https://github.com/???,https://storage.googleapis.com/subgraph-images/1601393873317zz.jpg, -Curve,Trades and liquidity details for Curve.fi DeFi platform,QmVaFg6W4vofpNSsMNVx1SNDn4n8bQm9ou95JH6FDiKqQ1,553731,,https://storage.googleapis.com/subgraph-images/default/sg-4.png, -Protocol Multy Raw,Aave protocol subgraph with all pools data,QmS8ZBEgXisX7yEm8daSQmmVkwQ6wH6WU1B4nBkYKrjHo2,276865,https://github.com/graphprotocol/aave-protocol,https://storage.googleapis.com/subgraph-images/1590485690460sticker_aave_telegram.png, -Gnosis protocol,Gnosis Protocol,QmQrapV3GN6GnkMByUbf6Xrw1xVqSNAbQtNkXsy6xKAs15,276865,https://github.com/gnosis/dex-subgraph,https://storage.googleapis.com/subgraph-images/1585926751418Gnosis_protocol_2019_logo_all_rgb_orange.png, -Mooniswap,stat for mooniswap,QmUBFkuoDzxHx2EPxwGQdBwshqTF79fzKQnXjTRNVHwg6e,138432,,https://storage.googleapis.com/subgraph-images/default/sg-4.png, -Marketplace,Decentraland's Marketplace,QmXdZDKnDX2o9qfupGDTXFM1xxspndHrHAGpbkWAPMs6Qk,138432,https://github.com/decentraland/marketplace,https://storage.googleapis.com/subgraph-images/1578327676983color.png, -Swap Subgraph,Swap Subgraph for Crypto.com DeFi,QmXhAzDVyYnxSLaeLGDpN941WJ3tyatqhyxh9ScwM82cgJ,138432,,https://storage.googleapis.com/subgraph-images/default/sg-6.png, -Known Origin,KnownOrigin artwork listings,QmTFeK8XKtA6hm2nZ8ectqyqTmx1ga8qiMpxQyyxfBrduv,130126,https://github.com/knownorigin/known-origin-subgraph,https://storage.googleapis.com/subgraph-images/1575098880182440px_LogoIcn.png, -Known Origin 2,Known Origin 2,QmXQdKGK1GFioQBuEPGSbugJkdfh35owJpiujgAZA1yXeg,55373,,, -Balancer Beta,Balancer beta,QmSvK3A8LU4p87sxskbsScovTKVUNt873ZgGMXWG1aMJaZ,41529,,, -Cream Swap Beta,"Crypto Rules Everything Around Me C.R.E.A.M.",QmREAAZS5ZB5nAABCutPRVBGVgaVHz21e1miwWXnpGZm51,27686,https://github.com/CreamFi/balancer-subgraph,https://storage.googleapis.com/subgraph-images/1599400535254CREAM_transparent_Secondary_straight_color.png, -mStable Governance,mStable Governance Subgraph,QmdXYzFaj3nqURSpx7jWvkiYnzVaMobTnQfXzPYYjnYLqv,27686,,https://storage.googleapis.com/subgraph-images/1599839414747mta.png, -Synthetix Exchanges,A subgraph on all exchanges in Synthetix,QmX9CNPbbYoFGvucHzNJkjTAMGKNWzUSFveWmgdoB6WVJm,27686,https://github.com/Synthetixio/synthetix-subgraph,https://storage.googleapis.com/subgraph-images/1569869352912Slack___jordan___Synthetix.jpg, -Uniswap V2,Piouls uniswap,Qmb6iDb7A8DHox3cLThFXkBbzKfBx8BbLjZwQTzspLWXG1,27686,,, -v39_8,arc index mainnet,QmWex7boz79MGkYmcLbjDg4N13kLsLQAtTfLyjcz6RgJ9i,13843,,https://storage.googleapis.com/subgraph-images/default/sg-4.png, -Yearn Vault ROI Dev,Development subgraph for yearn vault ROI,Qmdab4gjWa1yCACgAAcWjab2c16oqmPo6j5WtZjZ21UxcZ,13843,,https://storage.googleapis.com/subgraph-images/default/sg-5.png, -Compound V2,"A protocol for algorithmic efficient Money Markets.",QmTN6gMCBCYTgbis33eSvr6sLsQoQ3R6a2KzR7CqmMABQP,13843,,https://storage.googleapis.com/subgraph-images/1573145149921compound.png, -Opyn,Opyn Mainnet Subgraph,QmNVmy3hA6JVqZfMGoQc68GsB9GzGiEVLjhR1pHLY2xwuS,8305,https://https://github.com/aparnakr/OpynGraph,, -Uniswap,Uniswap data importer for Unspent.io,QmRpG1kMLJxnruvCScfs4JYPeHJEnJk1ZsEdhpfqaGPUHs,8305,,https://storage.googleapis.com/subgraph-images/default/sg-6.png, -ENS,"A secure & decentralized way to address resources on and off the blockchain using simple human-readable names. Access domains and transfer history.",QmY8Uzg61ttrogeTyCKLcDDR4gKNK44g9qkGDqeProkSHE,5537,,https://storage.googleapis.com/subgraph-images/1548795052635ENS_Logo_WHITE.png, -UMA,UMA Subgraph,QmVviUCWpxxZuwekyHe87vspJsaugG1KDkfqEwjm3788ku,5537,https://github.com/protofire/uma-subgraph,https://storage.googleapis.com/subgraph-images/1601561900375DsMClZnT_400x400.jpg, -AirSwap,"Trading history indexers delegates and more.",QmZ28XHpz1BNhR5jU2ABCqo2PqHutAPE8woaW1tYdDFDqV,2768,https://github.com/airswap/airswap-protocols,https://storage.googleapis.com/subgraph-images/158680119781426823563.png, -Aavegotchi Aragon,Aavegotchi Bonding Curve,QmY6Si48nCutHkofaXDL1mJd4XUxs2SCPeo4G6CT661z4P,2768,,https://storage.googleapis.com/subgraph-images/default/sg-7.png, -Unlock,Unlock on mainnet,QmR2uzq3Tt3htYTmefFwJ6eX2aYySY6ZRZkW9LZG39Byrh,1384,https://github.com/unlock-protocol/unlock-subgraph,https://storage.googleapis.com/subgraph-images/1569531464009unlock.png, -Tellor Dispute V2,tellor dispute center v2,QmfCaCcQnfBWXgCpbtf9kKWosVqUbeGLfEomYVJkMBqKj9,1384,,https://storage.googleapis.com/subgraph-images/default/sg-5.png, \ No newline at end of file diff --git a/packages/contracts/cli/mockData/bulkPhaseData/phase2.2-unsignal.csv b/packages/contracts/cli/mockData/bulkPhaseData/phase2.2-unsignal.csv deleted file mode 100644 index 3dc36230e..000000000 --- a/packages/contracts/cli/mockData/bulkPhaseData/phase2.2-unsignal.csv +++ /dev/null @@ -1,66 +0,0 @@ -Account,Subgraph Number,Amount (percentage) -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,0,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,1,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,2,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,3,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,4,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,5,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,6,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,7,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,8,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,9,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,10,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,11,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,12,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,13,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,14,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,15,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,16,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,17,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,18,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,19,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,20,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,21,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,22,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,23,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,24,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,25,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,26,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,27,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,28,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,29,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,30,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,31,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,32,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,33,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,34,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,35,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,36,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,37,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,38,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,39,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,40,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,41,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,42,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,43,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,44,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,45,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,46,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,47,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,48,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,49,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,50,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,51,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,52,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,53,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,54,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,55,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,56,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,57,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,58,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,59,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,60,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,61,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,62,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,63,50 -0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9,64,50 \ No newline at end of file diff --git a/packages/contracts/cli/mockData/subgraph-metadata/compound.json b/packages/contracts/cli/mockData/subgraph-metadata/compound.json deleted file mode 100644 index 47aa33d96..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/compound.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Compound is an open-source protocol for algorithmic, efficient Money Markets on the Ethereum blockchain.", - "displayName": "Compound", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmeMR3qK7wfAuSns4PpdFVZZcsCoLa7wEPQbrZTBQNKGWq", - "codeRepository": "https://github.com/graphprotocol/compound-V2-subgraph", - "website": "https://compound.finance/" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/decentraland.json b/packages/contracts/cli/mockData/subgraph-metadata/decentraland.json deleted file mode 100644 index 19fcdcfc8..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/decentraland.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "A decentralized virtual world that runs on open standards. Find districts, parcels, auctions, and more.", - "displayName": "Decentraland", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmVMtgVvEJLqmH3PZzcYVp5t8ni1v61e2M1rDVkcRo9WCz", - "codeRepository": "https://github.com/graphprotocol/decentraland-subgraph", - "website": "https://decentraland.org/" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/ens.json b/packages/contracts/cli/mockData/subgraph-metadata/ens.json deleted file mode 100644 index 9f918e6b7..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/ens.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "A secure & decentralized way to address resources on and off the blockchain using simple, human-readable names. Access domains and transfer history.", - "displayName": "ENS", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmUqD4MMAXQvbNX3FbWNP43gmDFFdQPmQrn8CT9kNEb7Rs", - "codeRepository": "https://github.com/ensdomains/ens-subgraph", - "website": "https://ens.domains/" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/ipfsHashes.txt b/packages/contracts/cli/mockData/subgraph-metadata/ipfsHashes.txt deleted file mode 100644 index 944bb1179..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/ipfsHashes.txt +++ /dev/null @@ -1,10 +0,0 @@ -Uniswap Image: QmSaK8PKxNWPv3QMMdjp8bYvQxnpU277DowPMwCUr7dAxS -Compound Image: QmeMR3qK7wfAuSns4PpdFVZZcsCoLa7wEPQbrZTBQNKGWq -Decentraland Image: QmVMtgVvEJLqmH3PZzcYVp5t8ni1v61e2M1rDVkcRo9WCz -ENS Image: QmUqD4MMAXQvbNX3FbWNP43gmDFFdQPmQrn8CT9kNEb7Rs -Livepeer Image: QmcTyMcTpkSrRs8Q7tUBPqA6ektwL7x5DEZCsEpoveXxe1 -Maker Image: QmdJ2g7fbk1XDh24NBCwWNSUZ8jY1XxpG9ukXhLAhanP6C -Melon Image: QmQpuowYwm5c7XYXmEbSGsP6EqTU7vEWBJGN3NhJLQZ7wq -Moloch Image: QmSLfbgC7wrmufnr4ekLJtzYT1YfoQFPRsFpCRrHsxr8ED -Origin Image: QmdNkVFiDjStPhCgQfnLUg8agwCK5yQQfmfivyeJJHDeDf -The Graph Image: QmTFK5DZc58XrTqhuuDTYoaq29ndnwoHX5TAW1bZr5EMpq diff --git a/packages/contracts/cli/mockData/subgraph-metadata/ipfsUpload.txt b/packages/contracts/cli/mockData/subgraph-metadata/ipfsUpload.txt deleted file mode 100644 index 0a6272db4..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/ipfsUpload.txt +++ /dev/null @@ -1,10 +0,0 @@ -QmSaK8PKxNWPv3QMMdjp8bYvQxnpU277DowPMwCUr7dAxS -QmeMR3qK7wfAuSns4PpdFVZZcsCoLa7wEPQbrZTBQNKGWq -QmVMtgVvEJLqmH3PZzcYVp5t8ni1v61e2M1rDVkcRo9WCz -QmUqD4MMAXQvbNX3FbWNP43gmDFFdQPmQrn8CT9kNEb7Rs -QmcTyMcTpkSrRs8Q7tUBPqA6ektwL7x5DEZCsEpoveXxe1 -QmdJ2g7fbk1XDh24NBCwWNSUZ8jY1XxpG9ukXhLAhanP6C -QmQpuowYwm5c7XYXmEbSGsP6EqTU7vEWBJGN3NhJLQZ7wq -QmSLfbgC7wrmufnr4ekLJtzYT1YfoQFPRsFpCRrHsxr8ED -QmdNkVFiDjStPhCgQfnLUg8agwCK5yQQfmfivyeJJHDeDf -QmTFK5DZc58XrTqhuuDTYoaq29ndnwoHX5TAW1bZr5EMpq diff --git a/packages/contracts/cli/mockData/subgraph-metadata/livepeer.json b/packages/contracts/cli/mockData/subgraph-metadata/livepeer.json deleted file mode 100644 index 071e8072b..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/livepeer.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "A protocol for affordable and reliable video encoding. Find transcoders, staking rounds, and rewards.", - "displayName": "Livepeer", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmcTyMcTpkSrRs8Q7tUBPqA6ektwL7x5DEZCsEpoveXxe1", - "codeRepository": "https://github.com/livepeer/livepeerjs/tree/master/packages/subgraph", - "website": "https://livepeer.org/" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/maker.json b/packages/contracts/cli/mockData/subgraph-metadata/maker.json deleted file mode 100644 index 481a65daa..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/maker.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Maker is a protocol for collateralized stable coin creation.", - "displayName": "Maker", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmdJ2g7fbk1XDh24NBCwWNSUZ8jY1XxpG9ukXhLAhanP6C", - "codeRepository": "https://github.com/makerdao", - "website": "https://makerdao.com/en/" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/melon.json b/packages/contracts/cli/mockData/subgraph-metadata/melon.json deleted file mode 100644 index f96a440c7..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/melon.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Technology operated and regulated funds.", - "displayName": "Melon", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmQpuowYwm5c7XYXmEbSGsP6EqTU7vEWBJGN3NhJLQZ7wq", - "codeRepository": "https://github.com/melonproject/melon-subgraph", - "website": "https://melonport.com" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/moloch.json b/packages/contracts/cli/mockData/subgraph-metadata/moloch.json deleted file mode 100644 index 07fe02345..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/moloch.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Decentralized asset allocation", - "displayName": "Moloch", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmSLfbgC7wrmufnr4ekLJtzYT1YfoQFPRsFpCRrHsxr8ED", - "codeRepository": "https://github.com/MolochVentures/moloch-monorepo/", - "website": "https://molochdao.com/" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/origin.json b/packages/contracts/cli/mockData/subgraph-metadata/origin.json deleted file mode 100644 index 8aa9b4e6f..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/origin.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Origin is a protocol for creating peer-to-peer marketplaces using the Ethereum blockchain and IPFS.", - "displayName": "Origin", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmdNkVFiDjStPhCgQfnLUg8agwCK5yQQfmfivyeJJHDeDf", - "codeRepository": "https://github.com/graphprotocol/origin-subgraph", - "website": "https://www.originprotocol.com/en" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/compound.png b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/compound.png deleted file mode 100644 index 5402694b7..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/compound.png and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/decentraland.jpeg b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/decentraland.jpeg deleted file mode 100644 index bda473c64..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/decentraland.jpeg and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/ens.jpeg b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/ens.jpeg deleted file mode 100644 index 7a45c295e..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/ens.jpeg and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/eth.png b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/eth.png deleted file mode 100644 index 3dbd86d79..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/eth.png and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/livepeer.png b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/livepeer.png deleted file mode 100644 index 3b6af8f07..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/livepeer.png and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/maker.jpeg b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/maker.jpeg deleted file mode 100644 index 544d1f7f5..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/maker.jpeg and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/melon.png b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/melon.png deleted file mode 100644 index 9cbb8f514..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/melon.png and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/moloch.jpeg b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/moloch.jpeg deleted file mode 100644 index d2ab14a47..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/moloch.jpeg and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/origin.png b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/origin.png deleted file mode 100644 index a13e2313a..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/origin.png and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/thegraph.jpeg b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/thegraph.jpeg deleted file mode 100644 index f2c7618e8..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/thegraph.jpeg and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/uniswap.jpeg b/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/uniswap.jpeg deleted file mode 100644 index c98eeb55d..000000000 Binary files a/packages/contracts/cli/mockData/subgraph-metadata/subgraph-images/uniswap.jpeg and /dev/null differ diff --git a/packages/contracts/cli/mockData/subgraph-metadata/subgraphMetadatas.ts b/packages/contracts/cli/mockData/subgraph-metadata/subgraphMetadatas.ts deleted file mode 100644 index ee9fc05b7..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/subgraphMetadatas.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { jsonToSubgraphMetadata } from '../metadataHelpers' - -import compound from './compound.json' -import decentraland from './decentraland.json' -import ens from './ens.json' -import livepeer from './livepeer.json' -import maker from './maker.json' -import melon from './melon.json' -import moloch from './moloch.json' -import origin from './origin.json' -import thegraph from './thegraph.json' -import uniswap from './uniswap.json' - -const compoundMetadata = jsonToSubgraphMetadata(compound) -const decentralandMetadata = jsonToSubgraphMetadata(decentraland) -const ensMetadata = jsonToSubgraphMetadata(ens) -const livepeerMetadata = jsonToSubgraphMetadata(livepeer) -const makerMetadata = jsonToSubgraphMetadata(maker) -const melonMetadata = jsonToSubgraphMetadata(melon) -const molochMetadata = jsonToSubgraphMetadata(moloch) -const originMetadata = jsonToSubgraphMetadata(origin) -const thegraphMetadata = jsonToSubgraphMetadata(thegraph) -const uniswapMetadata = jsonToSubgraphMetadata(uniswap) - -export default { - compoundMetadata, - decentralandMetadata, - ensMetadata, - livepeerMetadata, - makerMetadata, - melonMetadata, - molochMetadata, - originMetadata, - thegraphMetadata, - uniswapMetadata, -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/thegraph.json b/packages/contracts/cli/mockData/subgraph-metadata/thegraph.json deleted file mode 100644 index e4e4ea504..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/thegraph.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "Scalable queries for a decentralized future.", - "displayName": "The Graph", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmTFK5DZc58XrTqhuuDTYoaq29ndnwoHX5TAW1bZr5EMpq", - "codeRepository": "https://github.com/graphprotocol/graph-network-subgraph", - "website": "https://thegraph.com/" -} diff --git a/packages/contracts/cli/mockData/subgraph-metadata/uniswap.json b/packages/contracts/cli/mockData/subgraph-metadata/uniswap.json deleted file mode 100644 index b334d13d6..000000000 --- a/packages/contracts/cli/mockData/subgraph-metadata/uniswap.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "description": "The subgraph tracks event based data, which updates each exchange to index the live data. It also stores historical data entities, which can be used, and queried to build historical data, which can be used for charts.", - "displayName": "Uniswap", - "image": "https://api.thegraph.com/ipfs/api/v0/cat?arg=QmSaK8PKxNWPv3QMMdjp8bYvQxnpU277DowPMwCUr7dAxS", - "codeRepository": "https://github.com/graphprotocol/uniswap-subgraph", - "website": "https://uniswap.info/" -} diff --git a/packages/contracts/cli/mockData/version-metadata/firstVersion.json b/packages/contracts/cli/mockData/version-metadata/firstVersion.json deleted file mode 100644 index c446587d9..000000000 --- a/packages/contracts/cli/mockData/version-metadata/firstVersion.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "v0.0.1", - "description": "First subgraph version" -} diff --git a/packages/contracts/cli/mockData/version-metadata/secondVersion.json b/packages/contracts/cli/mockData/version-metadata/secondVersion.json deleted file mode 100644 index a855e371f..000000000 --- a/packages/contracts/cli/mockData/version-metadata/secondVersion.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "v0.2.0", - "description": "Second Version" -} diff --git a/packages/contracts/cli/mockData/version-metadata/versionMetadatas.ts b/packages/contracts/cli/mockData/version-metadata/versionMetadatas.ts deleted file mode 100644 index 7ab789d0a..000000000 --- a/packages/contracts/cli/mockData/version-metadata/versionMetadatas.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { jsonToVersionMetadata } from '../../metadataHelpers' - -import first from './firstVersion.json' -import second from './secondVersion.json' - -const firstVersion = jsonToVersionMetadata(first) -const secondVersion = jsonToVersionMetadata(second) - -export default { - firstVersion, - secondVersion, -} diff --git a/packages/contracts/cli/network.ts b/packages/contracts/cli/network.ts deleted file mode 100644 index 18a072fcd..000000000 --- a/packages/contracts/cli/network.ts +++ /dev/null @@ -1,441 +0,0 @@ -import { LinkReferences } from 'hardhat/types' - -import { - providers, - utils, - Contract, - ContractFactory, - ContractTransaction, - Signer, - Overrides, - BigNumber, - PayableOverrides, - Wallet, -} from 'ethers' - -import { logger } from './logging' -import { AddressBook } from './address-book' -import { loadArtifact } from './artifacts' -import { defaultOverrides } from './defaults' -import { GraphToken } from '../build/types/GraphToken' -import { Interface } from 'ethers/lib/utils' -import { IL1Staking } from '../build/types/IL1Staking' -import { IL2Staking } from '../build/types/IL2Staking' - -const { keccak256, randomBytes, parseUnits, hexlify } = utils - -export const randomHexBytes = (n = 32): string => hexlify(randomBytes(n)) -export const toBN = (value: string | number | BigNumber): BigNumber => BigNumber.from(value) -export const toGRT = (value: string | number): BigNumber => { - return parseUnits(typeof value === 'number' ? value.toString() : value, '18') -} -export const getProvider = (providerUrl: string, network?: number): providers.JsonRpcProvider => - new providers.JsonRpcProvider(providerUrl, network) - -export const getChainID = (): number => { - return 4 // Only works for rinkeby right now -} - -export const hashHexString = (input: string): string => keccak256(`0x${input.replace(/^0x/, '')}`) - -type ContractParam = string | BigNumber | number | { [key: string]: any } -type DeployResult = { - contract: Contract - creationCodeHash: string - runtimeCodeHash: string - txHash: string - libraries?: { [libraryName: string]: string } -} - -// Simple sanity checks to make sure contracts from our address book have been deployed -export const isContractDeployed = async ( - name: string, - address: string | undefined, - addressBook: AddressBook, - provider: providers.Provider, - checkCreationCode = true, -): Promise => { - logger.info(`Checking for valid ${name} contract...`) - if (!address || address === '') { - logger.warn('This contract is not in our address book.') - return false - } - - const addressEntry = addressBook.getEntry(name) - - // If the contract is behind a proxy we check the Proxy artifact instead - const artifact = addressEntry.proxy === true ? loadArtifact('GraphProxy') : loadArtifact(name) - - if (checkCreationCode) { - const savedCreationCodeHash = addressEntry.creationCodeHash - let creationCodeHash: string - try { - creationCodeHash = hashHexString(artifact.bytecode) - } catch (error) { - // Noop - assume contract is not deployed - } - if (!savedCreationCodeHash || savedCreationCodeHash !== creationCodeHash) { - logger.warn(`creationCodeHash in our address book doesn't match ${name} artifacts`) - logger.info(`${savedCreationCodeHash} !== ${creationCodeHash}`) - return false - } - } - - const savedRuntimeCodeHash = addressEntry.runtimeCodeHash - const runtimeCodeHash = hashHexString(await provider.getCode(address)) - if (runtimeCodeHash === hashHexString('0x00') || runtimeCodeHash === hashHexString('0x')) { - logger.warn('No runtimeCode exists at the address in our address book') - return false - } - if (savedRuntimeCodeHash !== runtimeCodeHash) { - logger.warn(`runtimeCodeHash for ${address} does not match what's in our address book`) - logger.info(`${savedRuntimeCodeHash} !== ${runtimeCodeHash}`) - return false - } - return true -} - -export const waitTransaction = async ( - sender: Signer, - tx: ContractTransaction, -): Promise => { - const receipt = await sender.provider.waitForTransaction(tx.hash) - const networkName = (await sender.provider.getNetwork()).name - if (networkName === 'goerli') { - receipt.status // 1 = success, 0 = failure - ? logger.info(`Transaction succeeded: 'https://${networkName}.etherscan.io/tx/${tx.hash}'`) - : logger.warn(`Transaction failed: 'https://${networkName}.etherscan.io/tx/${tx.hash}'`) - } else { - receipt.status - ? logger.info(`Transaction succeeded: ${tx.hash}`) - : logger.warn(`Transaction failed: ${tx.hash}`) - } - return receipt -} - -export const sendTransaction = async ( - sender: Signer, - contract: Contract, - fn: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - params?: Array, - overrides?: PayableOverrides, -): Promise => { - // Setup overrides - if (overrides) { - params.push(overrides) - } else { - params.push(defaultOverrides) - } - - // Send transaction - const tx: ContractTransaction = await contract.connect(sender).functions[fn](...params) - if (tx === undefined) { - logger.error( - `It appears the function does not exist on this contract, or you have the wrong contract address`, - ) - throw new Error('Transaction error') - } - logger.info( - `> Sent transaction ${fn}: [${params.slice(0, -1)}] \n contract: ${ - contract.address - }\n txHash: ${tx.hash}`, - ) - - // Wait for transaction to be mined - return waitTransaction(sender, tx) -} - -export const getContractFactory = ( - name: string, - libraries?: { [libraryName: string]: string }, -): ContractFactory => { - const artifact = loadArtifact(name) - // Fixup libraries - if (libraries && Object.keys(libraries).length > 0) { - artifact.bytecode = linkLibraries(artifact, libraries) - } - return new ContractFactory(artifact.abi, artifact.bytecode) -} - -export const getContractAt = ( - name: string, - address: string, - signerOrProvider?: Signer | providers.Provider, -): Contract => { - return new Contract(address, loadArtifact(name).abi, signerOrProvider) -} - -export const deployProxy = async ( - implementationAddress: string, - proxyAdminAddress: string, - sender: Signer, - overrides?: Overrides, -): Promise => { - return deployContract( - 'GraphProxy', - [implementationAddress, proxyAdminAddress], - sender, - false, - overrides, - ) -} - -export const deployContract = async ( - name: string, - args: Array, - sender: Signer, - autolink = true, - overrides?: Overrides, -): Promise => { - // This function will autolink, that means it will automatically deploy external libraries - // and link them to the contract - const libraries = {} - if (autolink) { - const artifact = loadArtifact(name) - if (artifact.linkReferences && Object.keys(artifact.linkReferences).length > 0) { - for (const fileReferences of Object.values(artifact.linkReferences)) { - for (const libName of Object.keys(fileReferences)) { - const deployResult = await deployContract(libName, [], sender, false, overrides) - libraries[libName] = deployResult.contract.address - } - } - } - } - - // Deploy - const factory = getContractFactory(name, libraries) - let contract = await factory.connect(sender).deploy(...args) - const txHash = contract.deployTransaction.hash - logger.info(`> Deploy ${name}, txHash: ${txHash}`) - await sender.provider.waitForTransaction(txHash) - - // Receipt - const creationCodeHash = hashHexString(factory.bytecode) - const runtimeCodeHash = hashHexString(await sender.provider.getCode(contract.address)) - logger.info(`= CreationCodeHash: ${creationCodeHash}`) - logger.info(`= RuntimeCodeHash: ${runtimeCodeHash}`) - logger.info(`${name} has been deployed to address: ${contract.address}`) - - if (name == 'L1Staking') { - // Hack the contract into behaving like an IL1Staking - const iface = new Interface(loadArtifact('IL1Staking').abi) - contract = new Contract(contract.address, iface, sender) as unknown as IL1Staking - } else if (name == 'L2Staking') { - // Hack the contract into behaving like an IL2Staking - const iface = new Interface(loadArtifact('IL2Staking').abi) - contract = new Contract(contract.address, iface, sender) as unknown as IL2Staking - } - return { contract, creationCodeHash, runtimeCodeHash, txHash, libraries } -} - -export const deployContractWithProxy = async ( - proxyAdmin: Contract, - name: string, - args: Array, - sender: Signer, - buildAcceptProxyTx = false, - overrides?: Overrides, -): Promise => { - // Deploy implementation - const { contract } = await deployContract(name, [], sender, true, overrides) - - // Wrap implementation with proxy - const proxy = await wrapContractWithProxy( - proxyAdmin, - contract, - args, - sender, - buildAcceptProxyTx, - overrides, - ) - - // Use interface of contract but with the proxy address - return contract.attach(proxy.address) -} - -export const wrapContractWithProxy = async ( - proxyAdmin: Contract, - contract: Contract, - args: Array, - sender: Signer, - buildAcceptProxyTx = false, - overrides?: Overrides, -): Promise => { - // Deploy proxy - const { contract: proxy } = await deployProxy( - contract.address, - proxyAdmin.address, - sender, - overrides, - ) - - // Implementation accepts upgrade - const initTx = args ? await contract.populateTransaction.initialize(...args) : null - const acceptFunctionName = initTx ? 'acceptProxyAndCall' : 'acceptProxy' - const acceptFunctionParams = initTx - ? [contract.address, proxy.address, initTx.data] - : [contract.address, proxy.address] - if (buildAcceptProxyTx) { - logger.info( - ` - Copy this data in the Gnosis Multisig UI, or a similar app and call ${acceptFunctionName} - -------------------------------------------------------------------------------------- - > Contract Address: ${proxyAdmin.address} - > Implementation: ${contract.address} - > Proxy: ${proxy.address} - > Data: ${initTx && initTx.data} - `, - ) - } else { - await sendTransaction(sender, proxyAdmin, acceptFunctionName, acceptFunctionParams) - } - - return proxy -} - -export const deployContractAndSave = async ( - name: string, - args: Array, - sender: Signer, - addressBook: AddressBook, -): Promise => { - // Deploy the contract - const deployResult = await deployContract(name, args, sender) - - // Save address entry - addressBook.setEntry(name, { - address: deployResult.contract.address, - constructorArgs: args.length === 0 ? undefined : args.map((e) => e.toString()), - creationCodeHash: deployResult.creationCodeHash, - runtimeCodeHash: deployResult.runtimeCodeHash, - txHash: deployResult.txHash, - libraries: - deployResult.libraries && Object.keys(deployResult.libraries).length > 0 - ? deployResult.libraries - : undefined, - }) - logger.info('> Contract saved to address book') - - return deployResult.contract -} - -export const deployContractImplementationAndSave = async ( - name: string, - args: Array, - sender: Signer, - addressBook: AddressBook, -): Promise => { - // Deploy the contract - const deployResult = await deployContract(name, args, sender) - - // Save address entry - const entry = addressBook.getEntry(name) - entry.implementation = { - address: deployResult.contract.address, - constructorArgs: args.length === 0 ? undefined : args.map((e) => e.toString()), - creationCodeHash: deployResult.creationCodeHash, - runtimeCodeHash: deployResult.runtimeCodeHash, - txHash: deployResult.txHash, - libraries: - deployResult.libraries && Object.keys(deployResult.libraries).length > 0 - ? deployResult.libraries - : undefined, - } - addressBook.setEntry(name, entry) - logger.info('> Contract saved to address book') - - return deployResult.contract -} - -export const deployContractWithProxyAndSave = async ( - name: string, - args: Array, - sender: Signer, - addressBook: AddressBook, - buildAcceptProxyTx?: boolean, -): Promise => { - // Get the GraphProxyAdmin to own the GraphProxy for this contract - const proxyAdminEntry = addressBook.getEntry('GraphProxyAdmin') - if (!proxyAdminEntry) { - throw new Error('GraphProxyAdmin not detected in the config, must be deployed first!') - } - const proxyAdmin = getContractAt('GraphProxyAdmin', proxyAdminEntry.address) - - // Deploy implementation - const contract = await deployContractAndSave(name, [], sender, addressBook) - - // Wrap implementation with proxy - const proxy = await wrapContractWithProxy(proxyAdmin, contract, args, sender, buildAcceptProxyTx) - - // Overwrite address entry with proxy - const artifact = loadArtifact('GraphProxy') - const contractEntry = addressBook.getEntry(name) - addressBook.setEntry(name, { - address: proxy.address, - initArgs: args.length === 0 ? undefined : args.map((e) => e.toString()), - creationCodeHash: hashHexString(artifact.bytecode), - runtimeCodeHash: hashHexString(await sender.provider.getCode(proxy.address)), - txHash: proxy.deployTransaction.hash, - proxy: true, - implementation: contractEntry, - }) - logger.info('> Contract saved to address book') - - // Use interface of contract but with the proxy address - return contract.attach(proxy.address) -} - -export const linkLibraries = ( - artifact: { - bytecode: string - linkReferences?: LinkReferences - }, - libraries?: { [libraryName: string]: string }, -): string => { - let bytecode = artifact.bytecode - - if (libraries) { - if (artifact.linkReferences) { - for (const fileReferences of Object.values(artifact.linkReferences)) { - for (const [libName, fixups] of Object.entries(fileReferences)) { - const addr = libraries[libName] - if (addr === undefined) { - continue - } - - for (const fixup of fixups) { - bytecode = - bytecode.substr(0, 2 + fixup.start * 2) + - addr.substr(2) + - bytecode.substr(2 + (fixup.start + fixup.length) * 2) - } - } - } - } - } - return bytecode -} - -export const ensureAllowance = async ( - sender: Wallet, - spenderAddress: string, - token: GraphToken, - amount: BigNumber, -) => { - // check balance - const senderBalance = await token.balanceOf(sender.address) - if (senderBalance.lt(amount)) { - throw new Error('Sender balance is insufficient for the transfer') - } - - // check allowance - const allowance = await token.allowance(sender.address, spenderAddress) - if (allowance.gte(amount)) { - return - } - - // approve - logger.info('Approving token transfer') - return sendTransaction(sender, token, 'approve', [spenderAddress, amount]) -} diff --git a/packages/contracts/config/graph.arbitrum-hardhat.yml b/packages/contracts/config/graph.arbitrum-hardhat.yml index 6ae4d50d6..91a86d2c2 100644 --- a/packages/contracts/config/graph.arbitrum-hardhat.yml +++ b/packages/contracts/config/graph.arbitrum-hardhat.yml @@ -59,7 +59,6 @@ contracts: calls: - fn: "addMinter" minter: "${{RewardsManager.address}}" - - fn: "renounceMinter" - fn: "transferOwnership" owner: *governor L2Curation: diff --git a/packages/contracts/config/graph.hardhat.yml b/packages/contracts/config/graph.hardhat.yml index 9f7cc6f5d..1bb9e03bf 100644 --- a/packages/contracts/config/graph.hardhat.yml +++ b/packages/contracts/config/graph.hardhat.yml @@ -60,7 +60,6 @@ contracts: minter: "${{RewardsManager.address}}" - fn: "addMinter" minter: "${{L1GraphTokenGateway.address}}" - - fn: "renounceMinter" - fn: "transferOwnership" owner: *governor Curation: diff --git a/packages/contracts/contracts/arbitrum/IBridge.sol b/packages/contracts/contracts/arbitrum/IBridge.sol index ff78253fc..536ee075b 100644 --- a/packages/contracts/contracts/arbitrum/IBridge.sol +++ b/packages/contracts/contracts/arbitrum/IBridge.sol @@ -35,12 +35,7 @@ interface IBridge { bytes32 messageDataHash ); - event BridgeCallTriggered( - address indexed outbox, - address indexed destAddr, - uint256 amount, - bytes data - ); + event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data); event InboxToggle(address indexed inbox, bool enabled); diff --git a/packages/contracts/contracts/arbitrum/IOutbox.sol b/packages/contracts/contracts/arbitrum/IOutbox.sol index 687c86abf..2e4f05bd5 100644 --- a/packages/contracts/contracts/arbitrum/IOutbox.sol +++ b/packages/contracts/contracts/arbitrum/IOutbox.sol @@ -51,8 +51,7 @@ interface IOutbox { function l2ToL1OutputId() external view returns (bytes32); - function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) - external; + function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths) external; function outboxEntryExists(uint256 batchNum) external view returns (bool); } diff --git a/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol b/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol index b893fa262..839e1930b 100644 --- a/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol +++ b/packages/contracts/contracts/arbitrum/L1ArbitrumMessenger.sol @@ -29,7 +29,7 @@ import "./IInbox.sol"; import "./IOutbox.sol"; /// @notice L1 utility contract to assist with L1 <=> L2 interactions -/// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing +/// @dev this is an abstract contract instead of library so the functions can be easily overridden when testing abstract contract L1ArbitrumMessenger { event TxToL2(address indexed _from, address indexed _to, uint256 indexed _seqNum, bytes _data); diff --git a/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol b/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol index e03985bef..e34a29262 100644 --- a/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol +++ b/packages/contracts/contracts/arbitrum/L2ArbitrumMessenger.sol @@ -28,7 +28,7 @@ pragma solidity ^0.7.6; import "arbos-precompiles/arbos/builtin/ArbSys.sol"; /// @notice L2 utility contract to assist with L1 <=> L2 interactions -/// @dev this is an abstract contract instead of library so the functions can be easily overriden when testing +/// @dev this is an abstract contract instead of library so the functions can be easily overridden when testing abstract contract L2ArbitrumMessenger { address internal constant ARB_SYS_ADDRESS = address(100); diff --git a/packages/contracts/contracts/bancor/BancorFormula.sol b/packages/contracts/contracts/bancor/BancorFormula.sol index 9cb41a502..689eebaba 100644 --- a/packages/contracts/contracts/bancor/BancorFormula.sol +++ b/packages/contracts/contracts/bancor/BancorFormula.sol @@ -324,9 +324,7 @@ contract BancorFormula { uint256 _amount ) public view returns (uint256) { // validate input - require( - _supply > 0 && _reserveBalance > 0 && _totalRatio > 1 && _totalRatio <= MAX_RATIO * 2 - ); + require(_supply > 0 && _reserveBalance > 0 && _totalRatio > 1 && _totalRatio <= MAX_RATIO * 2); // special case for 0 amount if (_amount == 0) return 0; @@ -364,11 +362,7 @@ contract BancorFormula { ) public view returns (uint256) { // validate input require( - _supply > 0 && - _reserveBalance > 0 && - _totalRatio > 1 && - _totalRatio <= MAX_RATIO * 2 && - _amount <= _supply + _supply > 0 && _reserveBalance > 0 && _totalRatio > 1 && _totalRatio <= MAX_RATIO * 2 && _amount <= _supply ); // special case for 0 amount @@ -407,12 +401,7 @@ contract BancorFormula { * This functions assumes that "_expN < 2 ^ 256 / log(MAX_NUM - 1)", otherwise the multiplication should be replaced with a "safeMul". * Since we rely on unsigned-integer arithmetic and "base < 1" ==> "log(base) < 0", this function does not support "_baseN < _baseD". */ - function power( - uint256 _baseN, - uint256 _baseD, - uint32 _expN, - uint32 _expD - ) internal view returns (uint256, uint8) { + function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) internal view returns (uint256, uint8) { require(_baseN < MAX_NUM); uint256 baseLog; @@ -428,10 +417,7 @@ contract BancorFormula { return (optimalExp(baseLogTimesExp), MAX_PRECISION); } else { uint8 precision = findPositionInMaxExpArray(baseLogTimesExp); - return ( - generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), - precision - ); + return (generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), precision); } } @@ -642,37 +628,21 @@ contract BancorFormula { z = y = x - FIXED_1; w = (y * y) / FIXED_1; - res += - (z * (0x100000000000000000000000000000000 - y)) / - 0x100000000000000000000000000000000; + res += (z * (0x100000000000000000000000000000000 - y)) / 0x100000000000000000000000000000000; z = (z * w) / FIXED_1; // add y^01 / 01 - y^02 / 02 - res += - (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / - 0x200000000000000000000000000000000; + res += (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / 0x200000000000000000000000000000000; z = (z * w) / FIXED_1; // add y^03 / 03 - y^04 / 04 - res += - (z * (0x099999999999999999999999999999999 - y)) / - 0x300000000000000000000000000000000; + res += (z * (0x099999999999999999999999999999999 - y)) / 0x300000000000000000000000000000000; z = (z * w) / FIXED_1; // add y^05 / 05 - y^06 / 06 - res += - (z * (0x092492492492492492492492492492492 - y)) / - 0x400000000000000000000000000000000; + res += (z * (0x092492492492492492492492492492492 - y)) / 0x400000000000000000000000000000000; z = (z * w) / FIXED_1; // add y^07 / 07 - y^08 / 08 - res += - (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / - 0x500000000000000000000000000000000; + res += (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / 0x500000000000000000000000000000000; z = (z * w) / FIXED_1; // add y^09 / 09 - y^10 / 10 - res += - (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / - 0x600000000000000000000000000000000; + res += (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / 0x600000000000000000000000000000000; z = (z * w) / FIXED_1; // add y^11 / 11 - y^12 / 12 - res += - (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / - 0x700000000000000000000000000000000; + res += (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / 0x700000000000000000000000000000000; z = (z * w) / FIXED_1; // add y^13 / 13 - y^14 / 14 - res += - (z * (0x088888888888888888888888888888888 - y)) / - 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16 + res += (z * (0x088888888888888888888888888888888 - y)) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16 return res; } diff --git a/packages/contracts/contracts/curation/Curation.sol b/packages/contracts/contracts/curation/Curation.sol index 04c3a6217..bd3032046 100644 --- a/packages/contracts/contracts/curation/Curation.sol +++ b/packages/contracts/contracts/curation/Curation.sol @@ -57,12 +57,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @dev Emitted when `curator` burned `signal` for a `subgraphDeploymentID`. * The curator will receive `tokens` according to the value of the bonding curve. */ - event Burned( - address indexed curator, - bytes32 indexed subgraphDeploymentID, - uint256 tokens, - uint256 signal - ); + event Burned(address indexed curator, bytes32 indexed subgraphDeploymentID, uint256 tokens, uint256 signal); /** * @dev Emitted when `tokens` amount were collected for `subgraphDeploymentID` as part of fees @@ -113,11 +108,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @notice Update the minimum deposit amount to `_minimumCurationDeposit` * @param _minimumCurationDeposit Minimum amount of tokens required deposit */ - function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) - external - override - onlyGovernor - { + function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) external override onlyGovernor { _setMinimumCurationDeposit(_minimumCurationDeposit); } @@ -149,10 +140,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { require(msg.sender == address(staking()), "Caller must be the staking contract"); // Must be curated to accept tokens - require( - isCurated(_subgraphDeploymentID), - "Subgraph deployment must be curated to collect fees" - ); + require(isCurated(_subgraphDeploymentID), "Subgraph deployment must be curated to collect fees"); // Collect new funds into reserve CurationPool storage curationPool = pools[_subgraphDeploymentID]; @@ -193,9 +181,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { // If no signal token for the pool - create one if (address(curationPool.gcs) == address(0)) { // Use a minimal proxy to reduce gas cost - IGraphCurationToken gcs = IGraphCurationToken( - ClonesUpgradeable.clone(curationTokenMaster) - ); + IGraphCurationToken gcs = IGraphCurationToken(ClonesUpgradeable.clone(curationTokenMaster)); gcs.initialize(address(this)); curationPool.gcs = gcs; } @@ -238,10 +224,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { // Validations require(_signalIn != 0, "Cannot burn zero signal"); - require( - getCuratorSignal(curator, _subgraphDeploymentID) >= _signalIn, - "Cannot burn more signal than you own" - ); + require(getCuratorSignal(curator, _subgraphDeploymentID) >= _signalIn, "Cannot burn more signal than you own"); // Get the amount of tokens to refund based on returned signal uint256 tokensOut = signalToTokens(_subgraphDeploymentID, _signalIn); @@ -277,12 +260,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @param _subgraphDeploymentID Subgraph deployment curation poool * @return Amount of token reserves in the curation pool */ - function getCurationPoolTokens(bytes32 _subgraphDeploymentID) - external - view - override - returns (uint256) - { + function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { return pools[_subgraphDeploymentID].tokens; } @@ -301,12 +279,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of signal owned by a curator for the subgraph deployment */ - function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) - public - view - override - returns (uint256) - { + function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) public view override returns (uint256) { IGraphCurationToken gcs = pools[_subgraphDeploymentID].gcs; return (address(gcs) == address(0)) ? 0 : gcs.balanceOf(_curator); } @@ -316,12 +289,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @param _subgraphDeploymentID Subgraph deployment curation poool * @return Amount of signal minted for the subgraph deployment */ - function getCurationPoolSignal(bytes32 _subgraphDeploymentID) - public - view - override - returns (uint256) - { + function getCurationPoolSignal(bytes32 _subgraphDeploymentID) public view override returns (uint256) { IGraphCurationToken gcs = pools[_subgraphDeploymentID].gcs; return (address(gcs) == address(0)) ? 0 : gcs.totalSupply(); } @@ -334,12 +302,12 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @return Amount of signal that can be bought * @return Amount of tokens that will be burned as curation tax */ - function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - public - view - override - returns (uint256, uint256) - { + function tokensToSignal( + bytes32 _subgraphDeploymentID, + uint256 _tokensIn + ) public view override returns (uint256, uint256) { + // NOTE: We're aware that this function rounds down and tax can be 0 for small amounts + // of tokens but since minimumCurationDeposit is 1 GRT tax will always be greater than 0. uint256 curationTax = _tokensIn.mul(uint256(curationTaxPercentage)).div(MAX_PPM); uint256 signalOut = _tokensToSignal(_subgraphDeploymentID, _tokensIn.sub(curationTax)); return (signalOut, curationTax); @@ -351,20 +319,13 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @param _tokensIn Amount of tokens used to mint signal * @return Amount of signal that can be bought with tokens */ - function _tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - private - view - returns (uint256) - { + function _tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) private view returns (uint256) { // Get curation pool tokens and signal CurationPool memory curationPool = pools[_subgraphDeploymentID]; // Init curation pool if (curationPool.tokens == 0) { - require( - _tokensIn >= minimumCurationDeposit, - "Curation deposit is below minimum required" - ); + require(_tokensIn >= minimumCurationDeposit, "Curation deposit is below minimum required"); return BancorFormula(bondingCurve) .calculatePurchaseReturn( @@ -391,22 +352,11 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @param _signalIn Amount of signal to burn * @return Amount of tokens to get for the specified amount of signal */ - function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) - public - view - override - returns (uint256) - { + function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) public view override returns (uint256) { CurationPool memory curationPool = pools[_subgraphDeploymentID]; uint256 curationPoolSignal = getCurationPoolSignal(_subgraphDeploymentID); - require( - curationPool.tokens != 0, - "Subgraph deployment must be curated to perform calculations" - ); - require( - curationPoolSignal >= _signalIn, - "Signal must be above or equal to signal issued in the curation pool" - ); + require(curationPool.tokens != 0, "Subgraph deployment must be curated to perform calculations"); + require(curationPoolSignal >= _signalIn, "Signal must be above or equal to signal issued in the curation pool"); return BancorFormula(bondingCurve).calculateSaleReturn( @@ -425,10 +375,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { function _setDefaultReserveRatio(uint32 _defaultReserveRatio) private { // Reserve Ratio must be within 0% to 100% (inclusive, in PPM) require(_defaultReserveRatio != 0, "Default reserve ratio must be > 0"); - require( - _defaultReserveRatio <= MAX_PPM, - "Default reserve ratio cannot be higher than MAX_PPM" - ); + require(_defaultReserveRatio <= MAX_PPM, "Default reserve ratio cannot be higher than MAX_PPM"); defaultReserveRatio = _defaultReserveRatio; emit ParameterUpdated("defaultReserveRatio"); @@ -451,10 +398,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { * @param _percentage Curation tax charged when depositing GRT tokens in PPM */ function _setCurationTaxPercentage(uint32 _percentage) private { - require( - _percentage <= MAX_PPM, - "Curation tax percentage must be below or equal to MAX_PPM" - ); + require(_percentage <= MAX_PPM, "Curation tax percentage must be below or equal to MAX_PPM"); curationTaxPercentage = _percentage; emit ParameterUpdated("curationTaxPercentage"); @@ -466,10 +410,7 @@ contract Curation is CurationV2Storage, GraphUpgradeable { */ function _setCurationTokenMaster(address _curationTokenMaster) private { require(_curationTokenMaster != address(0), "Token master must be non-empty"); - require( - AddressUpgradeable.isContract(_curationTokenMaster), - "Token master must be a contract" - ); + require(AddressUpgradeable.isContract(_curationTokenMaster), "Token master must be a contract"); curationTokenMaster = _curationTokenMaster; emit ParameterUpdated("curationTokenMaster"); diff --git a/packages/contracts/contracts/curation/ICuration.sol b/packages/contracts/contracts/curation/ICuration.sol index dffff46cd..d92aa9c69 100644 --- a/packages/contracts/contracts/curation/ICuration.sol +++ b/packages/contracts/contracts/curation/ICuration.sol @@ -56,11 +56,7 @@ interface ICuration { * @param _tokensOutMin Expected minimum amount of tokens to receive * @return Tokens returned */ - function burn( - bytes32 _subgraphDeploymentID, - uint256 _signalIn, - uint256 _tokensOutMin - ) external returns (uint256); + function burn(bytes32 _subgraphDeploymentID, uint256 _signalIn, uint256 _tokensOutMin) external returns (uint256); /** * @notice Assign Graph Tokens collected as curation fees to the curation pool reserve. @@ -84,10 +80,7 @@ interface ICuration { * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of signal owned by a curator for the subgraph deployment */ - function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) - external - view - returns (uint256); + function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) external view returns (uint256); /** * @notice Get the amount of signal in a curation pool. @@ -111,10 +104,7 @@ interface ICuration { * @return Amount of signal that can be bought * @return Amount of tokens that will be burned as curation tax */ - function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - external - view - returns (uint256, uint256); + function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) external view returns (uint256, uint256); /** * @notice Calculate number of tokens to get when burning signal from a curation pool. @@ -122,10 +112,7 @@ interface ICuration { * @param _signalIn Amount of signal to burn * @return Amount of tokens to get for the specified amount of signal */ - function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) - external - view - returns (uint256); + function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) external view returns (uint256); /** * @notice Tax charged when curators deposit funds. diff --git a/packages/contracts/contracts/discovery/GNS.sol b/packages/contracts/contracts/discovery/GNS.sol index 1430288cc..3cbb9ca8a 100644 --- a/packages/contracts/contracts/discovery/GNS.sol +++ b/packages/contracts/contracts/discovery/GNS.sol @@ -100,11 +100,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { /** * @dev Emitted when a subgraph is created. */ - event SubgraphPublished( - uint256 indexed subgraphID, - bytes32 indexed subgraphDeploymentID, - uint32 reserveRatio - ); + event SubgraphPublished(uint256 indexed subgraphID, bytes32 indexed subgraphDeploymentID, uint32 reserveRatio); /** * @dev Emitted when a subgraph is upgraded to point to a new @@ -126,12 +122,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { /** * @dev Emitted when a curator withdraws GRT from a deprecated subgraph */ - event GRTWithdrawn( - uint256 indexed subgraphID, - address indexed curator, - uint256 nSignalBurnt, - uint256 withdrawnGRT - ); + event GRTWithdrawn(uint256 indexed subgraphID, address indexed curator, uint256 nSignalBurnt, uint256 withdrawnGRT); /** * @dev Emitted when the counterpart (L1/L2) GNS address is updated @@ -230,11 +221,10 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _subgraphID Subgraph ID * @param _subgraphMetadata IPFS hash for the subgraph metadata */ - function updateSubgraphMetadata(uint256 _subgraphID, bytes32 _subgraphMetadata) - external - override - onlySubgraphAuth(_subgraphID) - { + function updateSubgraphMetadata( + uint256 _subgraphID, + bytes32 _subgraphMetadata + ) external override onlySubgraphAuth(_subgraphID) { _setSubgraphMetadata(_subgraphID, _subgraphMetadata); } @@ -311,31 +301,18 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { if (subgraphData.nSignal != 0) { // Burn all version signal in the name pool for tokens (w/no slippage protection) // Sell all signal from the old deployment - uint256 tokens = curation.burn( - subgraphData.subgraphDeploymentID, - subgraphData.vSignal, - 0 - ); + uint256 tokens = curation.burn(subgraphData.subgraphDeploymentID, subgraphData.vSignal, 0); // Take the owner cut of the curation tax, add it to the total // Upgrade is only callable by the owner, we assume then that msg.sender = owner address subgraphOwner = msg.sender; - uint256 tokensWithTax = _chargeOwnerTax( - tokens, - subgraphOwner, - curation.curationTaxPercentage() - ); + uint256 tokensWithTax = _chargeOwnerTax(tokens, subgraphOwner, curation.curationTaxPercentage()); // Update pool: constant nSignal, vSignal can change (w/no slippage protection) // Buy all signal from the new deployment (subgraphData.vSignal, ) = curation.mint(_subgraphDeploymentID, tokensWithTax, 0); - emit SubgraphUpgraded( - _subgraphID, - subgraphData.vSignal, - tokensWithTax, - _subgraphDeploymentID - ); + emit SubgraphUpgraded(_subgraphID, subgraphData.vSignal, tokensWithTax, _subgraphDeploymentID); } // Update target deployment @@ -350,22 +327,13 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * Can only be done by the subgraph owner. * @param _subgraphID Subgraph ID */ - function deprecateSubgraph(uint256 _subgraphID) - external - override - notPaused - onlySubgraphAuth(_subgraphID) - { + function deprecateSubgraph(uint256 _subgraphID) external override notPaused onlySubgraphAuth(_subgraphID) { // Subgraph check SubgraphData storage subgraphData = _getSubgraphOrRevert(_subgraphID); // Burn signal only if it has any available if (subgraphData.nSignal != 0) { - subgraphData.withdrawableGRT = curation().burn( - subgraphData.subgraphDeploymentID, - subgraphData.vSignal, - 0 - ); + subgraphData.withdrawableGRT = curation().burn(subgraphData.subgraphDeploymentID, subgraphData.vSignal, 0); } // Deprecate the subgraph and do cleanup @@ -431,10 +399,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { // Curator balance checks address curator = msg.sender; uint256 curatorNSignal = subgraphData.curatorNSignal[curator]; - require( - _nSignal <= curatorNSignal, - "GNS: Curator cannot withdraw more nSignal than they have" - ); + require(_nSignal <= curatorNSignal, "GNS: Curator cannot withdraw more nSignal than they have"); // Get tokens for name signal amount to burn uint256 vSignal = nSignalToVSignal(_subgraphID, _nSignal); @@ -474,9 +439,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { // Move the signal subgraphData.curatorNSignal[curator] = subgraphData.curatorNSignal[curator].sub(_amount); - subgraphData.curatorNSignal[_recipient] = subgraphData.curatorNSignal[_recipient].add( - _amount - ); + subgraphData.curatorNSignal[_recipient] = subgraphData.curatorNSignal[_recipient].add(_amount); emit SignalTransferred(_subgraphID, curator, _recipient, _amount); } @@ -499,9 +462,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { require(curatorNSignal != 0, "GNS: No signal to withdraw GRT"); // Get curator share of tokens to be withdrawn - uint256 tokensOut = curatorNSignal.mul(subgraphData.withdrawableGRT).div( - subgraphData.nSignal - ); + uint256 tokensOut = curatorNSignal.mul(subgraphData.withdrawableGRT).div(subgraphData.nSignal); subgraphData.curatorNSignal[curator] = 0; subgraphData.nSignal = subgraphData.nSignal.sub(curatorNSignal); subgraphData.withdrawableGRT = subgraphData.withdrawableGRT.sub(tokensOut); @@ -518,22 +479,14 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _subgraphNumber The sequence number of the created subgraph * @param _subgraphMetadata IPFS hash for the subgraph metadata */ - function migrateLegacySubgraph( - address _graphAccount, - uint256 _subgraphNumber, - bytes32 _subgraphMetadata - ) external { + function migrateLegacySubgraph(address _graphAccount, uint256 _subgraphNumber, bytes32 _subgraphMetadata) external { // Must be an existing legacy subgraph - bool legacySubgraphExists = legacySubgraphData[_graphAccount][_subgraphNumber] - .subgraphDeploymentID != 0; + bool legacySubgraphExists = legacySubgraphData[_graphAccount][_subgraphNumber].subgraphDeploymentID != 0; require(legacySubgraphExists == true, "GNS: Subgraph does not exist"); // Must not be a claimed subgraph uint256 subgraphID = _buildLegacySubgraphID(_graphAccount, _subgraphNumber); - require( - legacySubgraphKeys[subgraphID].account == address(0), - "GNS: Subgraph was already claimed" - ); + require(legacySubgraphKeys[subgraphID].account == address(0), "GNS: Subgraph was already claimed"); // Store a reference for a legacy subgraph legacySubgraphKeys[subgraphID] = IGNS.LegacySubgraphKey({ @@ -592,16 +545,10 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _tokensIn Tokens being exchanged for subgraph signal * @return Amount of subgraph signal and curation tax */ - function tokensToNSignal(uint256 _subgraphID, uint256 _tokensIn) - public - view - override - returns ( - uint256, - uint256, - uint256 - ) - { + function tokensToNSignal( + uint256 _subgraphID, + uint256 _tokensIn + ) public view override returns (uint256, uint256, uint256) { SubgraphData storage subgraphData = _getSubgraphData(_subgraphID); (uint256 vSignal, uint256 curationTax) = curation().tokensToSignal( subgraphData.subgraphDeploymentID, @@ -617,12 +564,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _nSignalIn Subgraph signal being exchanged for tokens * @return Amount of tokens returned for an amount of subgraph signal */ - function nSignalToTokens(uint256 _subgraphID, uint256 _nSignalIn) - public - view - override - returns (uint256, uint256) - { + function nSignalToTokens(uint256 _subgraphID, uint256 _nSignalIn) public view override returns (uint256, uint256) { // Get subgraph or revert if not published // It does not make sense to convert signal from a disabled or non-existing one SubgraphData storage subgraphData = _getSubgraphOrRevert(_subgraphID); @@ -637,12 +579,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _vSignalIn Amount of subgraph deployment signal to exchange for subgraph signal * @return Amount of subgraph signal that can be bought */ - function vSignalToNSignal(uint256 _subgraphID, uint256 _vSignalIn) - public - view - override - returns (uint256) - { + function vSignalToNSignal(uint256 _subgraphID, uint256 _vSignalIn) public view override returns (uint256) { SubgraphData storage subgraphData = _getSubgraphData(_subgraphID); // Handle initialization by using 1:1 version to name signal @@ -659,12 +596,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _nSignalIn Subgraph signal being exchanged for subgraph deployment signal * @return Amount of subgraph deployment signal that can be returned */ - function nSignalToVSignal(uint256 _subgraphID, uint256 _nSignalIn) - public - view - override - returns (uint256) - { + function nSignalToVSignal(uint256 _subgraphID, uint256 _nSignalIn) public view override returns (uint256) { SubgraphData storage subgraphData = _getSubgraphData(_subgraphID); return subgraphData.vSignal.mul(_nSignalIn).div(subgraphData.nSignal); } @@ -675,12 +607,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _curator Curator address * @return Amount of subgraph signal owned by a curator */ - function getCuratorSignal(uint256 _subgraphID, address _curator) - public - view - override - returns (uint256) - { + function getCuratorSignal(uint256 _subgraphID, address _curator) public view override returns (uint256) { return _getSubgraphData(_subgraphID).curatorNSignal[_curator]; } @@ -699,12 +626,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @return account Account that created the subgraph (or 0 if it's not a legacy subgraph) * @return seqID Sequence number for the subgraph */ - function getLegacySubgraphKey(uint256 _subgraphID) - public - view - override - returns (address account, uint256 seqID) - { + function getLegacySubgraphKey(uint256 _subgraphID) public view override returns (address account, uint256 seqID) { LegacySubgraphKey storage legacySubgraphKey = legacySubgraphKeys[_subgraphID]; account = legacySubgraphKey.account; seqID = legacySubgraphKey.accountSeqID; @@ -822,12 +744,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _subgraphID Subgraph ID * @return Subgraph Data */ - function _getSubgraphData(uint256 _subgraphID) - internal - view - virtual - returns (SubgraphData storage) - { + function _getSubgraphData(uint256 _subgraphID) internal view virtual returns (SubgraphData storage) { // If there is a legacy subgraph created return it LegacySubgraphKey storage legacySubgraphKey = legacySubgraphKeys[_subgraphID]; if (legacySubgraphKey.account != address(0)) { @@ -851,11 +768,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * @param _subgraphID Subgraph ID * @return Subgraph Data */ - function _getSubgraphOrRevert(uint256 _subgraphID) - internal - view - returns (SubgraphData storage) - { + function _getSubgraphOrRevert(uint256 _subgraphID) internal view returns (SubgraphData storage) { SubgraphData storage subgraphData = _getSubgraphData(_subgraphID); require(_isPublished(subgraphData) == true, "GNS: Must be active"); return subgraphData; @@ -867,11 +780,7 @@ abstract contract GNS is GNSV3Storage, GraphUpgradeable, IGNS, Multicall { * Subgraph ID is the keccak hash of account+seqID * @return Subgraph ID */ - function _buildLegacySubgraphID(address _account, uint256 _seqID) - internal - pure - returns (uint256) - { + function _buildLegacySubgraphID(address _account, uint256 _seqID) internal pure returns (uint256) { return uint256(keccak256(abi.encodePacked(_account, _seqID))); } diff --git a/packages/contracts/contracts/discovery/IGNS.sol b/packages/contracts/contracts/discovery/IGNS.sol index c3a6e0378..9267c70d2 100644 --- a/packages/contracts/contracts/discovery/IGNS.sol +++ b/packages/contracts/contracts/discovery/IGNS.sol @@ -87,11 +87,7 @@ interface IGNS { * @param _subgraphDeploymentID Subgraph deployment ID of the new version * @param _versionMetadata IPFS hash for the subgraph version metadata */ - function publishNewVersion( - uint256 _subgraphID, - bytes32 _subgraphDeploymentID, - bytes32 _versionMetadata - ) external; + function publishNewVersion(uint256 _subgraphID, bytes32 _subgraphDeploymentID, bytes32 _versionMetadata) external; /** * @notice Deprecate a subgraph. The bonding curve is destroyed, the vSignal is burned, and the GNS @@ -109,11 +105,7 @@ interface IGNS { * @param _tokensIn The amount of tokens the nameCurator wants to deposit * @param _nSignalOutMin Expected minimum amount of name signal to receive */ - function mintSignal( - uint256 _subgraphID, - uint256 _tokensIn, - uint256 _nSignalOutMin - ) external; + function mintSignal(uint256 _subgraphID, uint256 _tokensIn, uint256 _nSignalOutMin) external; /** * @notice Burn signal for a subgraph and return the GRT. @@ -121,11 +113,7 @@ interface IGNS { * @param _nSignal The amount of nSignal the nameCurator wants to burn * @param _tokensOutMin Expected minimum amount of tokens to receive */ - function burnSignal( - uint256 _subgraphID, - uint256 _nSignal, - uint256 _tokensOutMin - ) external; + function burnSignal(uint256 _subgraphID, uint256 _nSignal, uint256 _tokensOutMin) external; /** * @notice Move subgraph signal from sender to `_recipient` @@ -133,11 +121,7 @@ interface IGNS { * @param _recipient Address to send the signal to * @param _amount The amount of nSignal to transfer */ - function transferSignal( - uint256 _subgraphID, - address _recipient, - uint256 _amount - ) external; + function transferSignal(uint256 _subgraphID, address _recipient, uint256 _amount) external; /** * @notice Withdraw tokens from a deprecated subgraph. @@ -176,14 +160,7 @@ interface IGNS { * @param _tokensIn Tokens being exchanged for subgraph signal * @return Amount of subgraph signal and curation tax */ - function tokensToNSignal(uint256 _subgraphID, uint256 _tokensIn) - external - view - returns ( - uint256, - uint256, - uint256 - ); + function tokensToNSignal(uint256 _subgraphID, uint256 _tokensIn) external view returns (uint256, uint256, uint256); /** * @notice Calculate tokens returned for an amount of subgraph signal. @@ -191,10 +168,7 @@ interface IGNS { * @param _nSignalIn Subgraph signal being exchanged for tokens * @return Amount of tokens returned for an amount of subgraph signal */ - function nSignalToTokens(uint256 _subgraphID, uint256 _nSignalIn) - external - view - returns (uint256, uint256); + function nSignalToTokens(uint256 _subgraphID, uint256 _nSignalIn) external view returns (uint256, uint256); /** * @notice Calculate subgraph signal to be returned for an amount of subgraph deployment signal. @@ -202,10 +176,7 @@ interface IGNS { * @param _vSignalIn Amount of subgraph deployment signal to exchange for subgraph signal * @return Amount of subgraph signal that can be bought */ - function vSignalToNSignal(uint256 _subgraphID, uint256 _vSignalIn) - external - view - returns (uint256); + function vSignalToNSignal(uint256 _subgraphID, uint256 _vSignalIn) external view returns (uint256); /** * @notice Calculate subgraph deployment signal to be returned for an amount of subgraph signal. @@ -213,10 +184,7 @@ interface IGNS { * @param _nSignalIn Subgraph signal being exchanged for subgraph deployment signal * @return Amount of subgraph deployment signal that can be returned */ - function nSignalToVSignal(uint256 _subgraphID, uint256 _nSignalIn) - external - view - returns (uint256); + function nSignalToVSignal(uint256 _subgraphID, uint256 _nSignalIn) external view returns (uint256); /** * @notice Get the amount of subgraph signal a curator has. @@ -224,10 +192,7 @@ interface IGNS { * @param _curator Curator address * @return Amount of subgraph signal owned by a curator */ - function getCuratorSignal(uint256 _subgraphID, address _curator) - external - view - returns (uint256); + function getCuratorSignal(uint256 _subgraphID, address _curator) external view returns (uint256); /** * @notice Return whether a subgraph is published. @@ -249,8 +214,5 @@ interface IGNS { * @return account Account that created the subgraph (or 0 if it's not a legacy subgraph) * @return seqID Sequence number for the subgraph */ - function getLegacySubgraphKey(uint256 _subgraphID) - external - view - returns (address account, uint256 seqID); + function getLegacySubgraphKey(uint256 _subgraphID) external view returns (address account, uint256 seqID); } diff --git a/packages/contracts/contracts/discovery/IServiceRegistry.sol b/packages/contracts/contracts/discovery/IServiceRegistry.sol index 25eb07477..da284a409 100644 --- a/packages/contracts/contracts/discovery/IServiceRegistry.sol +++ b/packages/contracts/contracts/discovery/IServiceRegistry.sol @@ -10,11 +10,7 @@ interface IServiceRegistry { function register(string calldata _url, string calldata _geohash) external; - function registerFor( - address _indexer, - string calldata _url, - string calldata _geohash - ) external; + function registerFor(address _indexer, string calldata _url, string calldata _geohash) external; function unregister() external; diff --git a/packages/contracts/contracts/discovery/L1GNS.sol b/packages/contracts/contracts/discovery/L1GNS.sol index a2d15e1a7..31e9b0fb3 100644 --- a/packages/contracts/contracts/discovery/L1GNS.sol +++ b/packages/contracts/contracts/discovery/L1GNS.sol @@ -60,10 +60,7 @@ contract L1GNS is GNS, L1GNSV1Storage { uint256 _maxSubmissionCost ) external payable notPartialPaused { require(!subgraphTransferredToL2[_subgraphID], "ALREADY_DONE"); - require( - msg.value == _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid)), - "INVALID_ETH_VALUE" - ); + require(msg.value == _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid)), "INVALID_ETH_VALUE"); SubgraphData storage subgraphData = _getSubgraphOrRevert(_subgraphID); // This is just like onlySubgraphAuth, but we want it to run after the subgraphTransferredToL2 check @@ -71,11 +68,7 @@ contract L1GNS is GNS, L1GNSV1Storage { require(ownerOf(_subgraphID) == msg.sender, "GNS: Must be authorized"); subgraphTransferredToL2[_subgraphID] = true; - uint256 curationTokens = curation().burn( - subgraphData.subgraphDeploymentID, - subgraphData.vSignal, - 0 - ); + uint256 curationTokens = curation().burn(subgraphData.subgraphDeploymentID, subgraphData.vSignal, 0); subgraphData.disabled = true; subgraphData.vSignal = 0; @@ -93,19 +86,9 @@ contract L1GNS is GNS, L1GNSV1Storage { subgraphData.nSignal = totalSignal.sub(ownerNSignal); subgraphData.withdrawableGRT = curationTokens.sub(tokensForL2); - bytes memory extraData = abi.encode( - uint8(IL2GNS.L1MessageCodes.RECEIVE_SUBGRAPH_CODE), - _subgraphID, - _l2Owner - ); + bytes memory extraData = abi.encode(uint8(IL2GNS.L1MessageCodes.RECEIVE_SUBGRAPH_CODE), _subgraphID, _l2Owner); - _sendTokensAndMessageToL2GNS( - tokensForL2, - _maxGas, - _gasPriceBid, - _maxSubmissionCost, - extraData - ); + _sendTokensAndMessageToL2GNS(tokensForL2, _maxGas, _gasPriceBid, _maxSubmissionCost, extraData); subgraphData.__DEPRECATED_reserveRatio = 0; _burnNFT(_subgraphID); @@ -138,10 +121,7 @@ contract L1GNS is GNS, L1GNSV1Storage { uint256 _maxSubmissionCost ) external payable notPartialPaused { require(subgraphTransferredToL2[_subgraphID], "!TRANSFERRED"); - require( - msg.value == _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid)), - "INVALID_ETH_VALUE" - ); + require(msg.value == _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid)), "INVALID_ETH_VALUE"); // The Arbitrum bridge will check this too, we just check here for an early exit require(_maxSubmissionCost != 0, "NO_SUBMISSION_COST"); @@ -165,13 +145,7 @@ contract L1GNS is GNS, L1GNSV1Storage { subgraphData.withdrawableGRT = withdrawableGRT.sub(tokensForL2); // Send the tokens and data to L2 using the L1GraphTokenGateway - _sendTokensAndMessageToL2GNS( - tokensForL2, - _maxGas, - _gasPriceBid, - _maxSubmissionCost, - extraData - ); + _sendTokensAndMessageToL2GNS(tokensForL2, _maxGas, _gasPriceBid, _maxSubmissionCost, extraData); emit CuratorBalanceSentToL2(_subgraphID, msg.sender, _beneficiary, tokensForL2); } diff --git a/packages/contracts/contracts/discovery/ServiceRegistry.sol b/packages/contracts/contracts/discovery/ServiceRegistry.sol index 228210bf1..1eb1393d3 100644 --- a/packages/contracts/contracts/discovery/ServiceRegistry.sol +++ b/packages/contracts/contracts/discovery/ServiceRegistry.sol @@ -49,11 +49,7 @@ contract ServiceRegistry is ServiceRegistryV1Storage, GraphUpgradeable, IService * @param _url URL of the indexer service * @param _geohash Geohash of the indexer service location */ - function registerFor( - address _indexer, - string calldata _url, - string calldata _geohash - ) external override { + function registerFor(address _indexer, string calldata _url, string calldata _geohash) external override { _register(_indexer, _url, _geohash); } @@ -63,11 +59,7 @@ contract ServiceRegistry is ServiceRegistryV1Storage, GraphUpgradeable, IService * @param _url URL of the indexer service * @param _geohash Geohash of the indexer service location */ - function _register( - address _indexer, - string calldata _url, - string calldata _geohash - ) private { + function _register(address _indexer, string calldata _url, string calldata _geohash) private { require(_isAuth(_indexer), "!auth"); require(bytes(_url).length > 0, "Service must specify a URL"); diff --git a/packages/contracts/contracts/discovery/SubgraphNFT.sol b/packages/contracts/contracts/discovery/SubgraphNFT.sol index c6dadaa81..3c514718c 100644 --- a/packages/contracts/contracts/discovery/SubgraphNFT.sol +++ b/packages/contracts/contracts/discovery/SubgraphNFT.sol @@ -114,11 +114,7 @@ contract SubgraphNFT is Governed, ERC721, ISubgraphNFT { * @param _tokenId ID of the NFT * @param _subgraphMetadata IPFS hash for the metadata */ - function setSubgraphMetadata(uint256 _tokenId, bytes32 _subgraphMetadata) - external - override - onlyMinter - { + function setSubgraphMetadata(uint256 _tokenId, bytes32 _subgraphMetadata) external override onlyMinter { require(_exists(_tokenId), "ERC721Metadata: URI set of nonexistent token"); _subgraphMetadataHashes[_tokenId] = _subgraphMetadata; emit SubgraphMetadataUpdated(_tokenId, _subgraphMetadata); @@ -127,24 +123,13 @@ contract SubgraphNFT is Governed, ERC721, ISubgraphNFT { // -- NFT display -- /// @inheritdoc ERC721 - function tokenURI(uint256 _tokenId) - public - view - override(ERC721, ISubgraphNFT) - returns (string memory) - { + function tokenURI(uint256 _tokenId) public view override(ERC721, ISubgraphNFT) returns (string memory) { require(_exists(_tokenId), "ERC721Metadata: URI query for nonexistent token"); // Delegates rendering of the metadata to the token descriptor if existing // This allows for some flexibility in adapting the token URI if (address(tokenDescriptor) != address(0)) { - return - tokenDescriptor.tokenURI( - minter, - _tokenId, - baseURI(), - _subgraphMetadataHashes[_tokenId] - ); + return tokenDescriptor.tokenURI(minter, _tokenId, baseURI(), _subgraphMetadataHashes[_tokenId]); } // Default token URI diff --git a/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol b/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol index 751db2353..81f6da696 100644 --- a/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol +++ b/packages/contracts/contracts/discovery/SubgraphNFTDescriptor.sol @@ -9,14 +9,12 @@ import "./ISubgraphNFTDescriptor.sol"; contract SubgraphNFTDescriptor is ISubgraphNFTDescriptor { /// @inheritdoc ISubgraphNFTDescriptor function tokenURI( - address, /* _minter */ - uint256, /* _tokenId */ + address /* _minter */, + uint256 /* _tokenId */, string calldata _baseURI, bytes32 _subgraphMetadata ) external pure override returns (string memory) { - bytes memory b58 = Base58Encoder.encode( - abi.encodePacked(Base58Encoder.sha256MultiHash, _subgraphMetadata) - ); + bytes memory b58 = Base58Encoder.encode(abi.encodePacked(Base58Encoder.sha256MultiHash, _subgraphMetadata)); if (bytes(_baseURI).length == 0) { return string(b58); } diff --git a/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol b/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol index dce0e830a..e8545dd4a 100644 --- a/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol +++ b/packages/contracts/contracts/discovery/erc1056/EthereumDIDRegistry.sol @@ -62,21 +62,13 @@ contract EthereumDIDRegistry { return signer; } - function validDelegate( - address identity, - bytes32 delegateType, - address delegate - ) public view returns (bool) { + function validDelegate(address identity, bytes32 delegateType, address delegate) public view returns (bool) { uint256 validity = delegates[identity][keccak256(abi.encode(delegateType))][delegate]; /* solium-disable-next-line security/no-block-members*/ return (validity > block.timestamp); } - function changeOwner( - address identity, - address actor, - address newOwner - ) internal onlyOwner(identity, actor) { + function changeOwner(address identity, address actor, address newOwner) internal onlyOwner(identity, actor) { owners[identity] = newOwner; emit DIDOwnerChanged(identity, newOwner, changed[identity]); changed[identity] = block.number; @@ -86,13 +78,7 @@ contract EthereumDIDRegistry { changeOwner(identity, msg.sender, newOwner); } - function changeOwnerSigned( - address identity, - uint8 sigV, - bytes32 sigR, - bytes32 sigS, - address newOwner - ) public { + function changeOwnerSigned(address identity, uint8 sigV, bytes32 sigR, bytes32 sigS, address newOwner) public { bytes32 hash = keccak256( abi.encodePacked( bytes1(0x19), @@ -115,9 +101,7 @@ contract EthereumDIDRegistry { uint256 validity ) internal onlyOwner(identity, actor) { /* solium-disable-next-line security/no-block-members*/ - delegates[identity][keccak256(abi.encode(delegateType))][delegate] = - block.timestamp + - validity; + delegates[identity][keccak256(abi.encode(delegateType))][delegate] = block.timestamp + validity; emit DIDDelegateChanged( identity, delegateType, @@ -129,12 +113,7 @@ contract EthereumDIDRegistry { changed[identity] = block.number; } - function addDelegate( - address identity, - bytes32 delegateType, - address delegate, - uint256 validity - ) public { + function addDelegate(address identity, bytes32 delegateType, address delegate, uint256 validity) public { addDelegate(identity, msg.sender, delegateType, delegate, validity); } @@ -160,13 +139,7 @@ contract EthereumDIDRegistry { validity ) ); - addDelegate( - identity, - checkSignature(identity, sigV, sigR, sigS, hash), - delegateType, - delegate, - validity - ); + addDelegate(identity, checkSignature(identity, sigV, sigR, sigS, hash), delegateType, delegate, validity); } function revokeDelegate( @@ -178,21 +151,11 @@ contract EthereumDIDRegistry { /* solium-disable-next-line security/no-block-members*/ delegates[identity][keccak256(abi.encode(delegateType))][delegate] = block.timestamp; /* solium-disable-next-line security/no-block-members*/ - emit DIDDelegateChanged( - identity, - delegateType, - delegate, - block.timestamp, - changed[identity] - ); + emit DIDDelegateChanged(identity, delegateType, delegate, block.timestamp, changed[identity]); changed[identity] = block.number; } - function revokeDelegate( - address identity, - bytes32 delegateType, - address delegate - ) public { + function revokeDelegate(address identity, bytes32 delegateType, address delegate) public { revokeDelegate(identity, msg.sender, delegateType, delegate); } @@ -216,12 +179,7 @@ contract EthereumDIDRegistry { delegate ) ); - revokeDelegate( - identity, - checkSignature(identity, sigV, sigR, sigS, hash), - delegateType, - delegate - ); + revokeDelegate(identity, checkSignature(identity, sigV, sigR, sigS, hash), delegateType, delegate); } function setAttribute( @@ -232,22 +190,11 @@ contract EthereumDIDRegistry { uint256 validity ) internal onlyOwner(identity, actor) { /* solium-disable-next-line security/no-block-members*/ - emit DIDAttributeChanged( - identity, - name, - value, - block.timestamp + validity, - changed[identity] - ); + emit DIDAttributeChanged(identity, name, value, block.timestamp + validity, changed[identity]); changed[identity] = block.number; } - function setAttribute( - address identity, - bytes32 name, - bytes memory value, - uint256 validity - ) public { + function setAttribute(address identity, bytes32 name, bytes memory value, uint256 validity) public { setAttribute(identity, msg.sender, name, value, validity); } @@ -273,13 +220,7 @@ contract EthereumDIDRegistry { validity ) ); - setAttribute( - identity, - checkSignature(identity, sigV, sigR, sigS, hash), - name, - value, - validity - ); + setAttribute(identity, checkSignature(identity, sigV, sigR, sigS, hash), name, value, validity); } function revokeAttribute( @@ -292,11 +233,7 @@ contract EthereumDIDRegistry { changed[identity] = block.number; } - function revokeAttribute( - address identity, - bytes32 name, - bytes memory value - ) public { + function revokeAttribute(address identity, bytes32 name, bytes memory value) public { revokeAttribute(identity, msg.sender, name, value); } diff --git a/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol b/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol index 10a383f85..8de69f304 100644 --- a/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol +++ b/packages/contracts/contracts/discovery/erc1056/IEthereumDIDRegistry.sol @@ -5,10 +5,5 @@ pragma solidity ^0.7.6; interface IEthereumDIDRegistry { function identityOwner(address identity) external view returns (address); - function setAttribute( - address identity, - bytes32 name, - bytes calldata value, - uint256 validity - ) external; + function setAttribute(address identity, bytes32 name, bytes calldata value, uint256 validity) external; } diff --git a/packages/contracts/contracts/disputes/DisputeManager.sol b/packages/contracts/contracts/disputes/DisputeManager.sol index 8122b86b7..6700ec341 100644 --- a/packages/contracts/contracts/disputes/DisputeManager.sol +++ b/packages/contracts/contracts/disputes/DisputeManager.sol @@ -42,13 +42,10 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa // -- EIP-712 -- bytes32 private constant DOMAIN_TYPE_HASH = - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)" - ); + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); bytes32 private constant DOMAIN_NAME_HASH = keccak256("Graph Protocol"); bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); - bytes32 private constant DOMAIN_SALT = - 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; + bytes32 private constant DOMAIN_SALT = 0xa070ffb1cd7409649bf77822cce74495468e06dbfaef09556838bf188679b9c2; bytes32 private constant RECEIPT_TYPE_HASH = keccak256("Receipt(bytes32 requestCID,bytes32 responseCID,bytes32 subgraphDeploymentID)"); @@ -126,12 +123,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @dev Emitted when arbitrator draw a `disputeID` for `indexer` created by `fisherman`. * The event emits the amount `tokens` used as deposit and returned to the fisherman. */ - event DisputeDrawn( - bytes32 indexed disputeID, - address indexed indexer, - address indexed fisherman, - uint256 tokens - ); + event DisputeDrawn(bytes32 indexed disputeID, address indexed indexer, address indexed fisherman, uint256 tokens); /** * @dev Emitted when two disputes are in conflict to link them. @@ -156,10 +148,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa modifier onlyPendingDispute(bytes32 _disputeID) { require(isDisputeCreated(_disputeID), "Dispute does not exist"); - require( - disputes[_disputeID].status == IDisputeManager.DisputeStatus.Pending, - "Dispute must be pending" - ); + require(disputes[_disputeID].status == IDisputeManager.DisputeStatus.Pending, "Dispute must be pending"); _; } @@ -268,11 +257,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _qryPercentage Percentage slashing for query disputes * @param _idxPercentage Percentage slashing for indexing disputes */ - function setSlashingPercentage(uint32 _qryPercentage, uint32 _idxPercentage) - external - override - onlyGovernor - { + function setSlashingPercentage(uint32 _qryPercentage, uint32 _idxPercentage) external override onlyGovernor { _setSlashingPercentage(_qryPercentage, _idxPercentage); } @@ -349,12 +334,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _attestation Attestation * @return Indexer address */ - function getAttestationIndexer(Attestation memory _attestation) - public - view - override - returns (address) - { + function getAttestationIndexer(Attestation memory _attestation) public view override returns (address) { // Get attestation signer. Indexers signs with the allocationID address allocationID = _recoverAttestationSigner(_attestation); @@ -374,11 +354,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _attestationData Attestation bytes submitted by the fisherman * @param _deposit Amount of tokens staked as deposit */ - function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) - external - override - returns (bytes32) - { + function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) external override returns (bytes32) { // Get funds from submitter _pullSubmitterDeposit(_deposit); @@ -415,25 +391,12 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa Attestation memory attestation2 = _parseAttestation(_attestationData2); // Test that attestations are conflicting - require( - areConflictingAttestations(attestation1, attestation2), - "Attestations must be in conflict" - ); + require(areConflictingAttestations(attestation1, attestation2), "Attestations must be in conflict"); // Create the disputes // The deposit is zero for conflicting attestations - bytes32 dID1 = _createQueryDisputeWithAttestation( - fisherman, - 0, - attestation1, - _attestationData1 - ); - bytes32 dID2 = _createQueryDisputeWithAttestation( - fisherman, - 0, - attestation2, - _attestationData2 - ); + bytes32 dID1 = _createQueryDisputeWithAttestation(fisherman, 0, attestation1, _attestationData1); + bytes32 dID2 = _createQueryDisputeWithAttestation(fisherman, 0, attestation2, _attestationData2); // Store the linked disputes to be resolved disputes[dID1].relatedDisputeID = dID2; @@ -512,11 +475,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _allocationID The allocation to dispute * @param _deposit Amount of tokens staked as deposit */ - function createIndexingDispute(address _allocationID, uint256 _deposit) - external - override - returns (bytes32) - { + function createIndexingDispute(address _allocationID, uint256 _deposit) external override returns (bytes32) { // Get funds from submitter _pullSubmitterDeposit(_deposit); @@ -573,23 +532,14 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @notice Accept a dispute with ID `_disputeID` * @param _disputeID ID of the dispute to be accepted */ - function acceptDispute(bytes32 _disputeID) - external - override - onlyArbitrator - onlyPendingDispute(_disputeID) - { + function acceptDispute(bytes32 _disputeID) external override onlyArbitrator onlyPendingDispute(_disputeID) { Dispute storage dispute = disputes[_disputeID]; // store the dispute status dispute.status = IDisputeManager.DisputeStatus.Accepted; // Slash - (, uint256 tokensToReward) = _slashIndexer( - dispute.indexer, - dispute.fisherman, - dispute.disputeType - ); + (, uint256 tokensToReward) = _slashIndexer(dispute.indexer, dispute.fisherman, dispute.disputeType); // Give the fisherman their deposit back TokenUtils.pushTokens(graphToken(), dispute.fisherman, dispute.deposit); @@ -598,12 +548,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa rejectDispute(dispute.relatedDisputeID); } - emit DisputeAccepted( - _disputeID, - dispute.indexer, - dispute.fisherman, - dispute.deposit.add(tokensToReward) - ); + emit DisputeAccepted(_disputeID, dispute.indexer, dispute.fisherman, dispute.deposit.add(tokensToReward)); } /** @@ -611,12 +556,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @notice Reject a dispute with ID `_disputeID` * @param _disputeID ID of the dispute to be rejected */ - function rejectDispute(bytes32 _disputeID) - public - override - onlyArbitrator - onlyPendingDispute(_disputeID) - { + function rejectDispute(bytes32 _disputeID) public override onlyArbitrator onlyPendingDispute(_disputeID) { Dispute storage dispute = disputes[_disputeID]; // store dispute status @@ -639,12 +579,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @notice Ignore a dispute with ID `_disputeID` * @param _disputeID ID of the dispute to be disregarded */ - function drawDispute(bytes32 _disputeID) - public - override - onlyArbitrator - onlyPendingDispute(_disputeID) - { + function drawDispute(bytes32 _disputeID) public override onlyArbitrator onlyPendingDispute(_disputeID) { Dispute storage dispute = disputes[_disputeID]; // Return deposit to the fisherman @@ -667,8 +602,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa function _isDisputeInConflict(Dispute memory _dispute) private view returns (bool) { bytes32 relatedID = _dispute.relatedDisputeID; // this is so the check returns false when rejecting the related dispute. - return - relatedID != 0 && disputes[relatedID].status == IDisputeManager.DisputeStatus.Pending; + return relatedID != 0 && disputes[relatedID].status == IDisputeManager.DisputeStatus.Pending; } /** @@ -718,9 +652,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa uint256 slashableAmount = staking.getIndexerStakedTokens(_indexer); // slashable tokens // Get slash amount - slashAmount = _getSlashingPercentageForDisputeType(_disputeType).mul(slashableAmount).div( - MAX_PPM - ); + slashAmount = _getSlashingPercentageForDisputeType(_disputeType).mul(slashableAmount).div(MAX_PPM); require(slashAmount > 0, "Dispute has zero tokens to slash"); // Get rewards amount @@ -736,11 +668,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _disputeType Dispute type * @return Slashing percentage to use for the dispute type */ - function _getSlashingPercentageForDisputeType(DisputeType _disputeType) - private - view - returns (uint256) - { + function _getSlashingPercentageForDisputeType(DisputeType _disputeType) private view returns (uint256) { if (_disputeType == DisputeType.QueryDispute) return uint256(qrySlashingPercentage); if (_disputeType == DisputeType.IndexingDispute) return uint256(idxSlashingPercentage); return 0; @@ -751,11 +679,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa * @param _attestation The attestation struct * @return Signer address */ - function _recoverAttestationSigner(Attestation memory _attestation) - private - view - returns (address) - { + function _recoverAttestationSigner(Attestation memory _attestation) private view returns (address) { // Obtain the hash of the fully-encoded message, per EIP-712 encoding Receipt memory receipt = Receipt( _attestation.requestCID, @@ -766,11 +690,7 @@ contract DisputeManager is DisputeManagerV1Storage, GraphUpgradeable, IDisputeMa // Obtain the signer of the fully-encoded EIP-712 message hash // NOTE: The signer of the attestation is the indexer that served the request - return - ECDSA.recover( - messageHash, - abi.encodePacked(_attestation.r, _attestation.s, _attestation.v) - ); + return ECDSA.recover(messageHash, abi.encodePacked(_attestation.r, _attestation.s, _attestation.v)); } /** diff --git a/packages/contracts/contracts/disputes/IDisputeManager.sol b/packages/contracts/contracts/disputes/IDisputeManager.sol index 9c872f890..8c6668371 100644 --- a/packages/contracts/contracts/disputes/IDisputeManager.sol +++ b/packages/contracts/contracts/disputes/IDisputeManager.sol @@ -74,18 +74,14 @@ interface IDisputeManager { // -- Dispute -- - function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) - external - returns (bytes32); + function createQueryDispute(bytes calldata _attestationData, uint256 _deposit) external returns (bytes32); function createQueryDisputeConflict( bytes calldata _attestationData1, bytes calldata _attestationData2 ) external returns (bytes32, bytes32); - function createIndexingDispute(address _allocationID, uint256 _deposit) - external - returns (bytes32); + function createIndexingDispute(address _allocationID, uint256 _deposit) external returns (bytes32); function acceptDispute(bytes32 _disputeID) external; diff --git a/packages/contracts/contracts/epochs/EpochManager.sol b/packages/contracts/contracts/epochs/EpochManager.sol index 3f022d4af..281b63896 100644 --- a/packages/contracts/contracts/epochs/EpochManager.sol +++ b/packages/contracts/contracts/epochs/EpochManager.sol @@ -93,10 +93,7 @@ contract EpochManager is EpochManagerV1Storage, GraphUpgradeable, IEpochManager uint256 currentBlock = blockNum(); require(_block < currentBlock, "Can only retrieve past block hashes"); - require( - currentBlock < 256 || _block >= currentBlock - 256, - "Can only retrieve hashes for last 256 blocks" - ); + require(currentBlock < 256 || _block >= currentBlock - 256, "Can only retrieve hashes for last 256 blocks"); return blockhash(_block); } diff --git a/packages/contracts/contracts/gateway/GraphTokenGateway.sol b/packages/contracts/contracts/gateway/GraphTokenGateway.sol index ca2ad4c95..fb992afc2 100644 --- a/packages/contracts/contracts/gateway/GraphTokenGateway.sol +++ b/packages/contracts/contracts/gateway/GraphTokenGateway.sol @@ -19,10 +19,7 @@ abstract contract GraphTokenGateway is GraphUpgradeable, Pausable, Managed, ITok * @dev Check if the caller is the Controller's governor or this contract's pause guardian. */ modifier onlyGovernorOrGuardian() { - require( - msg.sender == controller.getGovernor() || msg.sender == pauseGuardian, - "Only Governor or Guardian" - ); + require(msg.sender == controller.getGovernor() || msg.sender == pauseGuardian, "Only Governor or Guardian"); _; } diff --git a/packages/contracts/contracts/gateway/ICallhookReceiver.sol b/packages/contracts/contracts/gateway/ICallhookReceiver.sol index ff0fbfab1..885b0cdb2 100644 --- a/packages/contracts/contracts/gateway/ICallhookReceiver.sol +++ b/packages/contracts/contracts/gateway/ICallhookReceiver.sol @@ -15,9 +15,5 @@ interface ICallhookReceiver { * @param _amount Amount of tokens that were transferred * @param _data ABI-encoded callhook data */ - function onTokenTransfer( - address _from, - uint256 _amount, - bytes calldata _data - ) external; + function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external; } diff --git a/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol b/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol index cfa71e6a0..7fad927ad 100644 --- a/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol +++ b/packages/contracts/contracts/gateway/L1GraphTokenGateway.sol @@ -207,10 +207,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess * @param _l2IssuancePerBlock New issuancePerBlock that has been set in L2 * @param _updateBlockNum L1 Block number at which issuancePerBlock was updated in L2 */ - function updateL2MintAllowance(uint256 _l2IssuancePerBlock, uint256 _updateBlockNum) - external - onlyGovernor - { + function updateL2MintAllowance(uint256 _l2IssuancePerBlock, uint256 _updateBlockNum) external onlyGovernor { require(_updateBlockNum < block.number, "BLOCK_MUST_BE_PAST"); require(_updateBlockNum > lastL2MintAllowanceUpdateBlock, "BLOCK_MUST_BE_INCREMENTING"); accumulatedL2MintAllowanceSnapshot = accumulatedL2MintAllowanceAtBlock(_updateBlockNum); @@ -290,30 +287,15 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess { bytes memory extraData; (from, maxSubmissionCost, extraData) = _parseOutboundData(_data); - require( - extraData.length == 0 || callhookAllowlist[msg.sender] == true, - "CALL_HOOK_DATA_NOT_ALLOWED" - ); + require(extraData.length == 0 || callhookAllowlist[msg.sender] == true, "CALL_HOOK_DATA_NOT_ALLOWED"); require(maxSubmissionCost != 0, "NO_SUBMISSION_COST"); outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData); } { - L2GasParams memory gasParams = L2GasParams( - maxSubmissionCost, - _maxGas, - _gasPriceBid - ); + L2GasParams memory gasParams = L2GasParams(maxSubmissionCost, _maxGas, _gasPriceBid); // transfer tokens to escrow token.transferFrom(from, escrow, _amount); - seqNum = sendTxToL2( - inbox, - l2Counterpart, - from, - msg.value, - 0, - gasParams, - outboundCalldata - ); + seqNum = sendTxToL2(inbox, l2Counterpart, from, msg.value, 0, gasParams, outboundCalldata); } } emit DepositInitiated(_l1Token, from, _to, seqNum, _amount); @@ -425,15 +407,7 @@ contract L1GraphTokenGateway is Initializable, GraphTokenGateway, L1ArbitrumMess * @return Base ether value required to keep retryable ticket alive * @return Additional data sent to L2 */ - function _parseOutboundData(bytes calldata _data) - private - view - returns ( - address, - uint256, - bytes memory - ) - { + function _parseOutboundData(bytes calldata _data) private view returns (address, uint256, bytes memory) { address from; uint256 maxSubmissionCost; bytes memory extraData; diff --git a/packages/contracts/contracts/governance/Controller.sol b/packages/contracts/contracts/governance/Controller.sol index bc287d2be..affb29a05 100644 --- a/packages/contracts/contracts/governance/Controller.sol +++ b/packages/contracts/contracts/governance/Controller.sol @@ -32,10 +32,7 @@ contract Controller is Governed, Pausable, IController { * @dev Check if the caller is the governor or pause guardian. */ modifier onlyGovernorOrGuardian() { - require( - msg.sender == governor || msg.sender == pauseGuardian, - "Only Governor or Guardian can call" - ); + require(msg.sender == governor || msg.sender == pauseGuardian, "Only Governor or Guardian can call"); _; } @@ -53,11 +50,7 @@ contract Controller is Governed, Pausable, IController { * @param _id Contract id (keccak256 hash of contract name) * @param _contractAddress Contract address */ - function setContractProxy(bytes32 _id, address _contractAddress) - external - override - onlyGovernor - { + function setContractProxy(bytes32 _id, address _contractAddress) external override onlyGovernor { require(_contractAddress != address(0), "Contract address must be set"); _registry[_id] = _contractAddress; emit SetContractProxy(_id, _contractAddress); diff --git a/packages/contracts/contracts/l2/curation/IL2Curation.sol b/packages/contracts/contracts/l2/curation/IL2Curation.sol index 235eec28a..bbbfd82ff 100644 --- a/packages/contracts/contracts/l2/curation/IL2Curation.sol +++ b/packages/contracts/contracts/l2/curation/IL2Curation.sol @@ -14,9 +14,7 @@ interface IL2Curation { * @param _tokensIn Amount of Graph Tokens to deposit * @return Signal minted */ - function mintTaxFree(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - external - returns (uint256); + function mintTaxFree(bytes32 _subgraphDeploymentID, uint256 _tokensIn) external returns (uint256); /** * @notice Calculate amount of signal that can be bought with tokens in a curation pool, @@ -25,10 +23,7 @@ interface IL2Curation { * @param _tokensIn Amount of tokens used to mint signal * @return Amount of signal that can be bought */ - function tokensToSignalNoTax(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - external - view - returns (uint256); + function tokensToSignalNoTax(bytes32 _subgraphDeploymentID, uint256 _tokensIn) external view returns (uint256); /** * @notice Calculate the amount of tokens that would be recovered if minting signal with @@ -38,8 +33,8 @@ interface IL2Curation { * @param _tokensIn Amount of tokens used to mint signal * @return Amount of tokens that would be recovered after minting and burning signal */ - function tokensToSignalToTokensNoTax(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - external - view - returns (uint256); + function tokensToSignalToTokensNoTax( + bytes32 _subgraphDeploymentID, + uint256 _tokensIn + ) external view returns (uint256); } diff --git a/packages/contracts/contracts/l2/curation/L2Curation.sol b/packages/contracts/contracts/l2/curation/L2Curation.sol index c18c10423..4d51bf3f1 100644 --- a/packages/contracts/contracts/l2/curation/L2Curation.sol +++ b/packages/contracts/contracts/l2/curation/L2Curation.sol @@ -59,12 +59,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @dev Emitted when `curator` burned `signal` for a `subgraphDeploymentID`. * The curator will receive `tokens` according to the value of the bonding curve. */ - event Burned( - address indexed curator, - bytes32 indexed subgraphDeploymentID, - uint256 tokens, - uint256 signal - ); + event Burned(address indexed curator, bytes32 indexed subgraphDeploymentID, uint256 tokens, uint256 signal); /** * @dev Emitted when `tokens` amount were collected for `subgraphDeploymentID` as part of fees @@ -116,11 +111,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @notice Update the minimum deposit amount to `_minimumCurationDeposit` * @param _minimumCurationDeposit Minimum amount of tokens required deposit */ - function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) - external - override - onlyGovernor - { + function setMinimumCurationDeposit(uint256 _minimumCurationDeposit) external override onlyGovernor { _setMinimumCurationDeposit(_minimumCurationDeposit); } @@ -152,10 +143,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { require(msg.sender == address(staking()), "Caller must be the staking contract"); // Must be curated to accept tokens - require( - isCurated(_subgraphDeploymentID), - "Subgraph deployment must be curated to collect fees" - ); + require(isCurated(_subgraphDeploymentID), "Subgraph deployment must be curated to collect fees"); // Collect new funds into reserve CurationPool storage curationPool = pools[_subgraphDeploymentID]; @@ -196,9 +184,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { // If no signal token for the pool - create one if (address(curationPool.gcs) == address(0)) { // Use a minimal proxy to reduce gas cost - IGraphCurationToken gcs = IGraphCurationToken( - ClonesUpgradeable.clone(curationTokenMaster) - ); + IGraphCurationToken gcs = IGraphCurationToken(ClonesUpgradeable.clone(curationTokenMaster)); gcs.initialize(address(this)); curationPool.gcs = gcs; } @@ -232,13 +218,10 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _tokensIn Amount of Graph Tokens to deposit * @return Signal minted */ - function mintTaxFree(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - external - override - notPartialPaused - onlyGNS - returns (uint256) - { + function mintTaxFree( + bytes32 _subgraphDeploymentID, + uint256 _tokensIn + ) external override notPartialPaused onlyGNS returns (uint256) { // Need to deposit some funds require(_tokensIn != 0, "Cannot deposit zero tokens"); @@ -256,9 +239,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { // If no signal token for the pool - create one if (address(curationPool.gcs) == address(0)) { // Use a minimal proxy to reduce gas cost - IGraphCurationToken gcs = IGraphCurationToken( - ClonesUpgradeable.clone(curationTokenMaster) - ); + IGraphCurationToken gcs = IGraphCurationToken(ClonesUpgradeable.clone(curationTokenMaster)); gcs.initialize(address(this)); curationPool.gcs = gcs; } @@ -299,10 +280,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { // Validations require(_signalIn != 0, "Cannot burn zero signal"); - require( - getCuratorSignal(curator, _subgraphDeploymentID) >= _signalIn, - "Cannot burn more signal than you own" - ); + require(getCuratorSignal(curator, _subgraphDeploymentID) >= _signalIn, "Cannot burn more signal than you own"); // Get the amount of tokens to refund based on returned signal uint256 tokensOut = signalToTokens(_subgraphDeploymentID, _signalIn); @@ -337,12 +315,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _subgraphDeploymentID Subgraph deployment curation poool * @return Amount of token reserves in the curation pool */ - function getCurationPoolTokens(bytes32 _subgraphDeploymentID) - external - view - override - returns (uint256) - { + function getCurationPoolTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { return pools[_subgraphDeploymentID].tokens; } @@ -361,12 +334,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _subgraphDeploymentID Subgraph deployment curation pool * @return Amount of signal owned by a curator for the subgraph deployment */ - function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) - public - view - override - returns (uint256) - { + function getCuratorSignal(address _curator, bytes32 _subgraphDeploymentID) public view override returns (uint256) { IGraphCurationToken gcs = pools[_subgraphDeploymentID].gcs; return (address(gcs) == address(0)) ? 0 : gcs.balanceOf(_curator); } @@ -376,12 +344,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _subgraphDeploymentID Subgraph deployment curation poool * @return Amount of signal minted for the subgraph deployment */ - function getCurationPoolSignal(bytes32 _subgraphDeploymentID) - public - view - override - returns (uint256) - { + function getCurationPoolSignal(bytes32 _subgraphDeploymentID) public view override returns (uint256) { IGraphCurationToken gcs = pools[_subgraphDeploymentID].gcs; return (address(gcs) == address(0)) ? 0 : gcs.totalSupply(); } @@ -394,14 +357,15 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @return Amount of signal that can be bought * @return Amount of GRT that would be subtracted as curation tax */ - function tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - public - view - override - returns (uint256, uint256) - { - uint256 curationTax = _tokensIn.mul(uint256(curationTaxPercentage)).div(MAX_PPM); - uint256 signalOut = _tokensToSignal(_subgraphDeploymentID, _tokensIn.sub(curationTax)); + function tokensToSignal( + bytes32 _subgraphDeploymentID, + uint256 _tokensIn + ) public view override returns (uint256, uint256) { + // Calculate tokens after tax first, subtract that from the tokens in + // to get the curation tax to avoid rounding down to zero. + uint256 tokensAfterCurationTax = uint256(MAX_PPM).sub(curationTaxPercentage).mul(_tokensIn).div(MAX_PPM); + uint256 curationTax = _tokensIn.sub(tokensAfterCurationTax); + uint256 signalOut = _tokensToSignal(_subgraphDeploymentID, tokensAfterCurationTax); return (signalOut, curationTax); } @@ -412,12 +376,10 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _tokensIn Amount of tokens used to mint signal * @return Amount of signal that can be bought */ - function tokensToSignalNoTax(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - public - view - override - returns (uint256) - { + function tokensToSignalNoTax( + bytes32 _subgraphDeploymentID, + uint256 _tokensIn + ) public view override returns (uint256) { return _tokensToSignal(_subgraphDeploymentID, _tokensIn); } @@ -429,12 +391,10 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _tokensIn Amount of tokens used to mint signal * @return Amount of tokens that would be recovered after minting and burning signal */ - function tokensToSignalToTokensNoTax(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - external - view - override - returns (uint256) - { + function tokensToSignalToTokensNoTax( + bytes32 _subgraphDeploymentID, + uint256 _tokensIn + ) external view override returns (uint256) { require(_tokensIn != 0, "Can't calculate with 0 tokens"); uint256 signal = _tokensToSignal(_subgraphDeploymentID, _tokensIn); CurationPool memory curationPool = pools[_subgraphDeploymentID]; @@ -449,22 +409,11 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _signalIn Amount of signal to burn * @return Amount of tokens to get for an amount of signal */ - function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) - public - view - override - returns (uint256) - { + function signalToTokens(bytes32 _subgraphDeploymentID, uint256 _signalIn) public view override returns (uint256) { CurationPool memory curationPool = pools[_subgraphDeploymentID]; uint256 curationPoolSignal = getCurationPoolSignal(_subgraphDeploymentID); - require( - curationPool.tokens != 0, - "Subgraph deployment must be curated to perform calculations" - ); - require( - curationPoolSignal >= _signalIn, - "Signal must be above or equal to signal issued in the curation pool" - ); + require(curationPool.tokens != 0, "Subgraph deployment must be curated to perform calculations"); + require(curationPoolSignal >= _signalIn, "Signal must be above or equal to signal issued in the curation pool"); return curationPool.tokens.mul(_signalIn).div(curationPoolSignal); } @@ -486,10 +435,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _percentage Curation tax percentage charged when depositing GRT tokens */ function _setCurationTaxPercentage(uint32 _percentage) private { - require( - _percentage <= MAX_PPM, - "Curation tax percentage must be below or equal to MAX_PPM" - ); + require(_percentage <= MAX_PPM, "Curation tax percentage must be below or equal to MAX_PPM"); curationTaxPercentage = _percentage; emit ParameterUpdated("curationTaxPercentage"); @@ -501,10 +447,7 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { */ function _setCurationTokenMaster(address _curationTokenMaster) private { require(_curationTokenMaster != address(0), "Token master must be non-empty"); - require( - AddressUpgradeable.isContract(_curationTokenMaster), - "Token master must be a contract" - ); + require(AddressUpgradeable.isContract(_curationTokenMaster), "Token master must be a contract"); curationTokenMaster = _curationTokenMaster; emit ParameterUpdated("curationTokenMaster"); @@ -527,25 +470,16 @@ contract L2Curation is CurationV2Storage, GraphUpgradeable, IL2Curation { * @param _tokensIn Amount of tokens used to mint signal * @return Amount of signal that can be bought with tokens */ - function _tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) - private - view - returns (uint256) - { + function _tokensToSignal(bytes32 _subgraphDeploymentID, uint256 _tokensIn) private view returns (uint256) { // Get curation pool tokens and signal CurationPool memory curationPool = pools[_subgraphDeploymentID]; // Init curation pool if (curationPool.tokens == 0) { - require( - _tokensIn >= minimumCurationDeposit, - "Curation deposit is below minimum required" - ); + require(_tokensIn >= minimumCurationDeposit, "Curation deposit is below minimum required"); return SIGNAL_PER_MINIMUM_DEPOSIT.add( - SIGNAL_PER_MINIMUM_DEPOSIT.mul(_tokensIn.sub(minimumCurationDeposit)).div( - minimumCurationDeposit - ) + SIGNAL_PER_MINIMUM_DEPOSIT.mul(_tokensIn.sub(minimumCurationDeposit)).div(minimumCurationDeposit) ); } diff --git a/packages/contracts/contracts/l2/discovery/L2GNS.sol b/packages/contracts/contracts/l2/discovery/L2GNS.sol index f2c4c9a83..34d47d400 100644 --- a/packages/contracts/contracts/l2/discovery/L2GNS.sol +++ b/packages/contracts/contracts/l2/discovery/L2GNS.sol @@ -91,10 +91,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { bytes calldata _data ) external override notPartialPaused onlyL2Gateway { require(_from == counterpartGNSAddress, "ONLY_L1_GNS_THROUGH_BRIDGE"); - (uint8 code, uint256 l1SubgraphID, address beneficiary) = abi.decode( - _data, - (uint8, uint256, address) - ); + (uint8 code, uint256 l1SubgraphID, address beneficiary) = abi.decode(_data, (uint8, uint256, address)); if (code == uint8(L1MessageCodes.RECEIVE_SUBGRAPH_CODE)) { _receiveSubgraphFromL1(l1SubgraphID, beneficiary, _amount); @@ -138,10 +135,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { { // This can't revert because the bridge ensures that _tokensIn is > 0, // and the minimum curation in L2 is 1 wei GRT - uint256 tokensAfter = curation.tokensToSignalToTokensNoTax( - _subgraphDeploymentID, - tokens - ); + uint256 tokensAfter = curation.tokensToSignalToTokensNoTax(_subgraphDeploymentID, tokens); roundingError = tokens.sub(tokensAfter).mul(MAX_PPM).div(tokens); } if (roundingError <= MAX_ROUNDING_ERROR) { @@ -151,11 +145,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { emit SubgraphUpgraded(_l2SubgraphID, vSignal, tokens, _subgraphDeploymentID); } else { graphToken().transfer(msg.sender, tokens); - emit CuratorBalanceReturnedToBeneficiary( - getUnaliasedL1SubgraphID(_l2SubgraphID), - msg.sender, - tokens - ); + emit CuratorBalanceReturnedToBeneficiary(getUnaliasedL1SubgraphID(_l2SubgraphID), msg.sender, tokens); emit SubgraphUpgraded(_l2SubgraphID, vSignal, 0, _subgraphDeploymentID); } @@ -209,31 +199,18 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { if (subgraphData.nSignal != 0) { // Burn all version signal in the name pool for tokens (w/no slippage protection) // Sell all signal from the old deployment - uint256 tokens = curation.burn( - subgraphData.subgraphDeploymentID, - subgraphData.vSignal, - 0 - ); + uint256 tokens = curation.burn(subgraphData.subgraphDeploymentID, subgraphData.vSignal, 0); // Take the owner cut of the curation tax, add it to the total // Upgrade is only callable by the owner, we assume then that msg.sender = owner address subgraphOwner = msg.sender; - uint256 tokensWithTax = _chargeOwnerTax( - tokens, - subgraphOwner, - curation.curationTaxPercentage() - ); + uint256 tokensWithTax = _chargeOwnerTax(tokens, subgraphOwner, curation.curationTaxPercentage()); // Update pool: constant nSignal, vSignal can change (w/no slippage protection) // Buy all signal from the new deployment (subgraphData.vSignal, ) = curation.mint(_subgraphDeploymentID, tokensWithTax, 0); - emit SubgraphUpgraded( - _subgraphID, - subgraphData.vSignal, - tokensWithTax, - _subgraphDeploymentID - ); + emit SubgraphUpgraded(_subgraphID, subgraphData.vSignal, tokensWithTax, _subgraphDeploymentID); } // Update target deployment @@ -256,12 +233,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { * @param _l2SubgraphID L2 subgraph ID * @return L1subgraph ID */ - function getUnaliasedL1SubgraphID(uint256 _l2SubgraphID) - public - pure - override - returns (uint256) - { + function getUnaliasedL1SubgraphID(uint256 _l2SubgraphID) public pure override returns (uint256) { return _l2SubgraphID - SUBGRAPH_ID_ALIAS_OFFSET; } @@ -273,11 +245,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { * @param _subgraphOwner Owner of the subgraph * @param _tokens Tokens to be deposited in the subgraph */ - function _receiveSubgraphFromL1( - uint256 _l1SubgraphID, - address _subgraphOwner, - uint256 _tokens - ) internal { + function _receiveSubgraphFromL1(uint256 _l1SubgraphID, address _subgraphOwner, uint256 _tokens) internal { uint256 l2SubgraphID = getAliasedL2SubgraphID(_l1SubgraphID); SubgraphData storage subgraphData = _getSubgraphData(l2SubgraphID); IL2GNS.SubgraphL2TransferData storage transferData = subgraphL2TransferData[l2SubgraphID]; @@ -307,11 +275,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { * @param _curator Curator address * @param _tokensIn The amount of tokens the nameCurator wants to deposit */ - function _mintSignalFromL1( - uint256 _l1SubgraphID, - address _curator, - uint256 _tokensIn - ) internal { + function _mintSignalFromL1(uint256 _l1SubgraphID, address _curator, uint256 _tokensIn) internal { uint256 l2SubgraphID = getAliasedL2SubgraphID(_l1SubgraphID); IL2GNS.SubgraphL2TransferData storage transferData = subgraphL2TransferData[l2SubgraphID]; SubgraphData storage subgraphData = _getSubgraphData(l2SubgraphID); @@ -321,10 +285,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { if (transferData.l2Done && !subgraphData.disabled) { // This can't revert because the bridge ensures that _tokensIn is > 0, // and the minimum curation in L2 is 1 wei GRT - uint256 tokensAfter = curation.tokensToSignalToTokensNoTax( - subgraphData.subgraphDeploymentID, - _tokensIn - ); + uint256 tokensAfter = curation.tokensToSignalToTokensNoTax(subgraphData.subgraphDeploymentID, _tokensIn); roundingError = _tokensIn.sub(tokensAfter).mul(MAX_PPM).div(_tokensIn); } // If subgraph transfer wasn't finished, we should send the tokens to the curator @@ -339,9 +300,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { // Update pools subgraphData.vSignal = subgraphData.vSignal.add(vSignal); subgraphData.nSignal = subgraphData.nSignal.add(nSignal); - subgraphData.curatorNSignal[_curator] = subgraphData.curatorNSignal[_curator].add( - nSignal - ); + subgraphData.curatorNSignal[_curator] = subgraphData.curatorNSignal[_curator].add(nSignal); emit SignalMinted(l2SubgraphID, _curator, nSignal, vSignal, _tokensIn); emit CuratorBalanceReceived(_l1SubgraphID, l2SubgraphID, _curator, _tokensIn); @@ -355,12 +314,7 @@ contract L2GNS is GNS, L2GNSV1Storage, IL2GNS { * @param _subgraphID Subgraph ID * @return Subgraph Data */ - function _getSubgraphData(uint256 _subgraphID) - internal - view - override - returns (SubgraphData storage) - { + function _getSubgraphData(uint256 _subgraphID) internal view override returns (SubgraphData storage) { // Return new subgraph type return subgraphs[_subgraphID]; } diff --git a/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol b/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol index 03417a59a..be8f212b8 100644 --- a/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol +++ b/packages/contracts/contracts/l2/gateway/L2GraphTokenGateway.sol @@ -39,12 +39,7 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran } /// Emitted when an incoming transfer is finalized, i.e. tokens were deposited from L1 to L2 - event DepositFinalized( - address indexed l1Token, - address indexed from, - address indexed to, - uint256 amount - ); + event DepositFinalized(address indexed l1Token, address indexed from, address indexed to, uint256 amount); /// Emitted when an outbound transfer is initiated, i.e. tokens are being withdrawn from L2 back to L1 event WithdrawalInitiated( @@ -68,10 +63,7 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran * gateway on L1. */ modifier onlyL1Counterpart() { - require( - msg.sender == AddressAliasHelper.applyL1ToL2Alias(l1Counterpart), - "ONLY_COUNTERPART_GATEWAY" - ); + require(msg.sender == AddressAliasHelper.applyL1ToL2Alias(l1Counterpart), "ONLY_COUNTERPART_GATEWAY"); _; } @@ -216,13 +208,7 @@ contract L2GraphTokenGateway is GraphTokenGateway, L2ArbitrumMessenger, Reentran 0, outboundCalldata.from, l1Counterpart, - getOutboundCalldata( - _l1Token, - outboundCalldata.from, - _to, - _amount, - outboundCalldata.extraData - ) + getOutboundCalldata(_l1Token, outboundCalldata.from, _to, _amount, outboundCalldata.extraData) ); // we don't need to track exitNums (b/c we have no fast exits) so we always use 0 diff --git a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol index 8b8cd92ab..6f701ec89 100644 --- a/packages/contracts/contracts/l2/staking/IL2StakingBase.sol +++ b/packages/contracts/contracts/l2/staking/IL2StakingBase.sol @@ -10,9 +10,5 @@ import { ICallhookReceiver } from "../../gateway/ICallhookReceiver.sol"; * @dev Note it includes only the L2-specific functionality, not the full IStaking interface. */ interface IL2StakingBase is ICallhookReceiver { - event TransferredDelegationReturnedToDelegator( - address indexed indexer, - address indexed delegator, - uint256 amount - ); + event TransferredDelegationReturnedToDelegator(address indexed indexer, address indexed delegator, uint256 amount); } diff --git a/packages/contracts/contracts/l2/staking/L2Staking.sol b/packages/contracts/contracts/l2/staking/L2Staking.sol index 7e561b990..3f9d28e5a 100644 --- a/packages/contracts/contracts/l2/staking/L2Staking.sol +++ b/packages/contracts/contracts/l2/staking/L2Staking.sol @@ -28,12 +28,7 @@ contract L2Staking is Staking, IL2StakingBase { * This is copied from IStakingExtension, but we can't inherit from it because we * don't implement the full interface here. */ - event StakeDelegated( - address indexed indexer, - address indexed delegator, - uint256 tokens, - uint256 shares - ); + event StakeDelegated(address indexed indexer, address indexed delegator, uint256 tokens, uint256 shares); /** * @dev Checks that the sender is the L2GraphTokenGateway as configured on the Controller. @@ -92,10 +87,7 @@ contract L2Staking is Staking, IL2StakingBase { * @param _amount Amount of tokens that were transferred * @param _indexerData struct containing the indexer's address */ - function _receiveIndexerStake( - uint256 _amount, - IL2Staking.ReceiveIndexerStakeData memory _indexerData - ) internal { + function _receiveIndexerStake(uint256 _amount, IL2Staking.ReceiveIndexerStakeData memory _indexerData) internal { address _indexer = _indexerData.indexer; // Deposit tokens into the indexer stake __stakes[_indexer].deposit(_amount); @@ -116,10 +108,7 @@ contract L2Staking is Staking, IL2StakingBase { * @param _amount Amount of tokens that were transferred * @param _delegationData struct containing the delegator's address and the indexer's address */ - function _receiveDelegation( - uint256 _amount, - IL2Staking.ReceiveDelegationData memory _delegationData - ) internal { + function _receiveDelegation(uint256 _amount, IL2Staking.ReceiveDelegationData memory _delegationData) internal { // Get the delegation pool of the indexer DelegationPool storage pool = __delegationPools[_delegationData.indexer]; Delegation storage delegation = pool.delegators[_delegationData.delegator]; @@ -132,11 +121,7 @@ contract L2Staking is Staking, IL2StakingBase { // or if the amount is under the minimum delegation (which could be part of a rounding attack), // return the tokens to the delegator graphToken().transfer(_delegationData.delegator, _amount); - emit TransferredDelegationReturnedToDelegator( - _delegationData.indexer, - _delegationData.delegator, - _amount - ); + emit TransferredDelegationReturnedToDelegator(_delegationData.indexer, _delegationData.delegator, _amount); } else { // Update the delegation pool pool.tokens = pool.tokens.add(_amount); @@ -145,12 +130,7 @@ contract L2Staking is Staking, IL2StakingBase { // Update the individual delegation delegation.shares = delegation.shares.add(shares); - emit StakeDelegated( - _delegationData.indexer, - _delegationData.delegator, - _amount, - shares - ); + emit StakeDelegated(_delegationData.indexer, _delegationData.delegator, _amount, shares); } } } diff --git a/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol b/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol index 3f7882b5c..0f5cf0ecb 100644 --- a/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol +++ b/packages/contracts/contracts/l2/token/GraphTokenUpgradeable.sol @@ -30,21 +30,16 @@ abstract contract GraphTokenUpgradeable is GraphUpgradeable, Governed, ERC20Burn /// @dev Hash of the EIP-712 Domain type bytes32 private immutable DOMAIN_TYPE_HASH = - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)" - ); + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); /// @dev Hash of the EIP-712 Domain name bytes32 private immutable DOMAIN_NAME_HASH = keccak256("Graph Token"); /// @dev Hash of the EIP-712 Domain version bytes32 private immutable DOMAIN_VERSION_HASH = keccak256("0"); /// @dev EIP-712 Domain salt - bytes32 private immutable DOMAIN_SALT = - 0xe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f5659591; // Randomly generated salt + bytes32 private immutable DOMAIN_SALT = 0xe33842a7acd1d5a1d28f25a931703e5605152dc48d64dc4716efdae1f5659591; // Randomly generated salt /// @dev Hash of the EIP-712 permit type bytes32 private immutable PERMIT_TYPEHASH = - keccak256( - "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" - ); + keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); // -- State -- @@ -94,9 +89,7 @@ abstract contract GraphTokenUpgradeable is GraphUpgradeable, Governed, ERC20Burn abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, - keccak256( - abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, nonces[_owner], _deadline) - ) + keccak256(abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, nonces[_owner], _deadline)) ) ); diff --git a/packages/contracts/contracts/payments/AllocationExchange.sol b/packages/contracts/contracts/payments/AllocationExchange.sol index 6a45d03ad..3a05112fe 100644 --- a/packages/contracts/contracts/payments/AllocationExchange.sol +++ b/packages/contracts/contracts/payments/AllocationExchange.sol @@ -31,7 +31,7 @@ contract AllocationExchange is Governed { // -- Constants -- - uint256 private constant MAX_UINT256 = 2**256 - 1; + uint256 private constant MAX_UINT256 = 2 ** 256 - 1; uint256 private constant SIGNATURE_LENGTH = 65; // -- State -- @@ -56,12 +56,7 @@ contract AllocationExchange is Governed { * @param _governor Account capable of withdrawing funds and setting the authority * @param _authority Account that can sign the vouchers that this contract will redeem */ - constructor( - IGraphToken _graphToken, - IStaking _staking, - address _governor, - address _authority - ) { + constructor(IGraphToken _graphToken, IStaking _staking, address _governor, address _authority) { require(_governor != address(0), "Exchange: governor must be set"); Governed._initialize(_governor); @@ -148,10 +143,7 @@ contract AllocationExchange is Governed { require(_voucher.signature.length == SIGNATURE_LENGTH, "Exchange: invalid signature"); // Already redeemed check - require( - !allocationsRedeemed[_voucher.allocationID], - "Exchange: allocation already redeemed" - ); + require(!allocationsRedeemed[_voucher.allocationID], "Exchange: allocation already redeemed"); // Signature check bytes32 messageHash = keccak256(abi.encodePacked(_voucher.allocationID, _voucher.amount)); diff --git a/packages/contracts/contracts/rewards/IRewardsManager.sol b/packages/contracts/contracts/rewards/IRewardsManager.sol index b70c13d64..511f1adf9 100644 --- a/packages/contracts/contracts/rewards/IRewardsManager.sol +++ b/packages/contracts/contracts/rewards/IRewardsManager.sol @@ -33,15 +33,9 @@ interface IRewardsManager { function getAccRewardsPerSignal() external view returns (uint256); - function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) - external - view - returns (uint256); - - function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID) - external - view - returns (uint256, uint256); + function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) external view returns (uint256); + + function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID) external view returns (uint256, uint256); function getRewards(address _allocationID) external view returns (uint256); diff --git a/packages/contracts/contracts/rewards/RewardsManager.sol b/packages/contracts/contracts/rewards/RewardsManager.sol index 2c405e76d..f19aad1a6 100644 --- a/packages/contracts/contracts/rewards/RewardsManager.sol +++ b/packages/contracts/contracts/rewards/RewardsManager.sol @@ -38,12 +38,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa /** * @dev Emitted when rewards are assigned to an indexer. */ - event RewardsAssigned( - address indexed indexer, - address indexed allocationID, - uint256 epoch, - uint256 amount - ); + event RewardsAssigned(address indexed indexer, address indexed allocationID, uint256 epoch, uint256 amount); /** * @dev Emitted when rewards are denied to an indexer. @@ -58,10 +53,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa // -- Modifiers -- modifier onlySubgraphAvailabilityOracle() { - require( - msg.sender == address(subgraphAvailabilityOracle), - "Caller must be the subgraph availability oracle" - ); + require(msg.sender == address(subgraphAvailabilityOracle), "Caller must be the subgraph availability oracle"); _; } @@ -103,11 +95,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa * @dev Sets the subgraph oracle allowed to denegate distribution of rewards to subgraphs. * @param _subgraphAvailabilityOracle Address of the subgraph availability oracle */ - function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) - external - override - onlyGovernor - { + function setSubgraphAvailabilityOracle(address _subgraphAvailabilityOracle) external override onlyGovernor { subgraphAvailabilityOracle = _subgraphAvailabilityOracle; emit ParameterUpdated("subgraphAvailabilityOracle"); } @@ -120,8 +108,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa function setMinimumSubgraphSignal(uint256 _minimumSubgraphSignal) external override { // Caller can be the SAO or the governor require( - msg.sender == address(subgraphAvailabilityOracle) || - msg.sender == controller.getGovernor(), + msg.sender == address(subgraphAvailabilityOracle) || msg.sender == controller.getGovernor(), "Not authorized" ); minimumSubgraphSignal = _minimumSubgraphSignal; @@ -136,11 +123,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa * @param _subgraphDeploymentID Subgraph deployment ID * @param _deny Whether to set the subgraph as denied for claiming rewards or not */ - function setDenied(bytes32 _subgraphDeploymentID, bool _deny) - external - override - onlySubgraphAvailabilityOracle - { + function setDenied(bytes32 _subgraphDeploymentID, bool _deny) external override onlySubgraphAvailabilityOracle { _setDenied(_subgraphDeploymentID, _deny); } @@ -216,12 +199,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa * @param _subgraphDeploymentID Subgraph deployment * @return Accumulated rewards for subgraph */ - function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) - public - view - override - returns (uint256) - { + function getAccRewardsForSubgraph(bytes32 _subgraphDeploymentID) public view override returns (uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; // Get tokens signalled on the subgraph @@ -229,10 +207,9 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa // Only accrue rewards if over a threshold uint256 newRewards = (subgraphSignalledTokens >= minimumSubgraphSignal) // Accrue new rewards since last snapshot - ? getAccRewardsPerSignal() - .sub(subgraph.accRewardsPerSignalSnapshot) - .mul(subgraphSignalledTokens) - .div(FIXED_POINT_SCALING_FACTOR) + ? getAccRewardsPerSignal().sub(subgraph.accRewardsPerSignalSnapshot).mul(subgraphSignalledTokens).div( + FIXED_POINT_SCALING_FACTOR + ) : 0; return subgraph.accRewardsForSubgraph.add(newRewards); } @@ -243,12 +220,9 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa * @return Accumulated rewards per allocated token for the subgraph * @return Accumulated rewards for subgraph */ - function getAccRewardsPerAllocatedToken(bytes32 _subgraphDeploymentID) - public - view - override - returns (uint256, uint256) - { + function getAccRewardsPerAllocatedToken( + bytes32 _subgraphDeploymentID + ) public view override returns (uint256, uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; uint256 accRewardsForSubgraph = getAccRewardsForSubgraph(_subgraphDeploymentID); @@ -257,20 +231,15 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa subgraph.accRewardsForSubgraphSnapshot ); - uint256 subgraphAllocatedTokens = staking().getSubgraphAllocatedTokens( - _subgraphDeploymentID - ); + uint256 subgraphAllocatedTokens = staking().getSubgraphAllocatedTokens(_subgraphDeploymentID); if (subgraphAllocatedTokens == 0) { return (0, accRewardsForSubgraph); } - uint256 newRewardsPerAllocatedToken = newRewardsForSubgraph - .mul(FIXED_POINT_SCALING_FACTOR) - .div(subgraphAllocatedTokens); - return ( - subgraph.accRewardsPerAllocatedToken.add(newRewardsPerAllocatedToken), - accRewardsForSubgraph + uint256 newRewardsPerAllocatedToken = newRewardsForSubgraph.mul(FIXED_POINT_SCALING_FACTOR).div( + subgraphAllocatedTokens ); + return (subgraph.accRewardsPerAllocatedToken.add(newRewardsPerAllocatedToken), accRewardsForSubgraph); } // -- Updates -- @@ -294,11 +263,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa * @param _subgraphDeploymentID Subgraph deployment * @return Accumulated rewards for subgraph */ - function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) - external - override - returns (uint256) - { + function onSubgraphSignalUpdate(bytes32 _subgraphDeploymentID) external override returns (uint256) { // Called since `total signalled GRT` will change updateAccRewardsPerSignal(); @@ -317,16 +282,11 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa * @param _subgraphDeploymentID Subgraph deployment * @return Accumulated rewards per allocated token for a subgraph */ - function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) - public - override - returns (uint256) - { + function onSubgraphAllocationUpdate(bytes32 _subgraphDeploymentID) public override returns (uint256) { Subgraph storage subgraph = subgraphs[_subgraphDeploymentID]; - ( - uint256 accRewardsPerAllocatedToken, - uint256 accRewardsForSubgraph - ) = getAccRewardsPerAllocatedToken(_subgraphDeploymentID); + (uint256 accRewardsPerAllocatedToken, uint256 accRewardsForSubgraph) = getAccRewardsPerAllocatedToken( + _subgraphDeploymentID + ); subgraph.accRewardsPerAllocatedToken = accRewardsPerAllocatedToken; subgraph.accRewardsForSubgraphSnapshot = accRewardsForSubgraph; return subgraph.accRewardsPerAllocatedToken; @@ -345,15 +305,8 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa IStaking.Allocation memory alloc = staking().getAllocation(_allocationID); - (uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken( - alloc.subgraphDeploymentID - ); - return - _calcRewards( - alloc.tokens, - alloc.accRewardsPerAllocatedToken, - accRewardsPerAllocatedToken - ); + (uint256 accRewardsPerAllocatedToken, ) = getAccRewardsPerAllocatedToken(alloc.subgraphDeploymentID); + return _calcRewards(alloc.tokens, alloc.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken); } /** @@ -385,9 +338,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa require(msg.sender == address(staking), "Caller must be the staking contract"); IStaking.Allocation memory alloc = staking.getAllocation(_allocationID); - uint256 accRewardsPerAllocatedToken = onSubgraphAllocationUpdate( - alloc.subgraphDeploymentID - ); + uint256 accRewardsPerAllocatedToken = onSubgraphAllocationUpdate(alloc.subgraphDeploymentID); // Do not do rewards on denied subgraph deployments ID if (isDenied(alloc.subgraphDeploymentID)) { @@ -396,11 +347,7 @@ contract RewardsManager is RewardsManagerV4Storage, GraphUpgradeable, IRewardsMa } // Calculate rewards accrued by this allocation - uint256 rewards = _calcRewards( - alloc.tokens, - alloc.accRewardsPerAllocatedToken, - accRewardsPerAllocatedToken - ); + uint256 rewards = _calcRewards(alloc.tokens, alloc.accRewardsPerAllocatedToken, accRewardsPerAllocatedToken); if (rewards > 0) { // Mint directly to staking contract for the reward amount // The staking contract will do bookkeeping of the reward and diff --git a/packages/contracts/contracts/staking/IL1StakingBase.sol b/packages/contracts/contracts/staking/IL1StakingBase.sol index 58749a247..fad2136c2 100644 --- a/packages/contracts/contracts/staking/IL1StakingBase.sol +++ b/packages/contracts/contracts/staking/IL1StakingBase.sol @@ -39,9 +39,7 @@ interface IL1StakingBase { * @dev This function can only be called by the governor. * @param _l1GraphTokenLockTransferTool Address of the L1GraphTokenLockTransferTool contract */ - function setL1GraphTokenLockTransferTool( - IL1GraphTokenLockTransferTool _l1GraphTokenLockTransferTool - ) external; + function setL1GraphTokenLockTransferTool(IL1GraphTokenLockTransferTool _l1GraphTokenLockTransferTool) external; /** * @notice Send an indexer's stake to L2. diff --git a/packages/contracts/contracts/staking/IStakingBase.sol b/packages/contracts/contracts/staking/IStakingBase.sol index 5f1dec63c..b30d00499 100644 --- a/packages/contracts/contracts/staking/IStakingBase.sol +++ b/packages/contracts/contracts/staking/IStakingBase.sol @@ -380,8 +380,5 @@ interface IStakingBase is IStakingData { * @param _subgraphDeploymentID Deployment ID for the subgraph * @return Total tokens allocated to subgraph */ - function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) - external - view - returns (uint256); + function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view returns (uint256); } diff --git a/packages/contracts/contracts/staking/IStakingExtension.sol b/packages/contracts/contracts/staking/IStakingExtension.sol index 36e6dce92..6a60dc9eb 100644 --- a/packages/contracts/contracts/staking/IStakingExtension.sol +++ b/packages/contracts/contracts/staking/IStakingExtension.sol @@ -32,12 +32,7 @@ interface IStakingExtension is IStakingData { * @dev Emitted when `delegator` delegated `tokens` to the `indexer`, the delegator * gets `shares` for the delegation pool proportionally to the tokens staked. */ - event StakeDelegated( - address indexed indexer, - address indexed delegator, - uint256 tokens, - uint256 shares - ); + event StakeDelegated(address indexed indexer, address indexed delegator, uint256 tokens, uint256 shares); /** * @dev Emitted when `delegator` undelegated `tokens` from `indexer`. @@ -54,22 +49,13 @@ interface IStakingExtension is IStakingData { /** * @dev Emitted when `delegator` withdrew delegated `tokens` from `indexer`. */ - event StakeDelegatedWithdrawn( - address indexed indexer, - address indexed delegator, - uint256 tokens - ); + event StakeDelegatedWithdrawn(address indexed indexer, address indexed delegator, uint256 tokens); /** * @dev Emitted when `indexer` was slashed for a total of `tokens` amount. * Tracks `reward` amount of tokens given to `beneficiary`. */ - event StakeSlashed( - address indexed indexer, - uint256 tokens, - uint256 reward, - address beneficiary - ); + event StakeSlashed(address indexed indexer, uint256 tokens, uint256 reward, address beneficiary); /** * @dev Emitted when `caller` set `slasher` address as `allowed` to slash stakes. @@ -139,12 +125,7 @@ interface IStakingExtension is IStakingData { * @param _reward Amount of reward tokens to send to a beneficiary * @param _beneficiary Address of a beneficiary to receive a reward for the slashing */ - function slash( - address _indexer, - uint256 _tokens, - uint256 _reward, - address _beneficiary - ) external; + function slash(address _indexer, uint256 _tokens, uint256 _reward, address _beneficiary) external; /** * @notice Return the delegation from a delegator to an indexer. @@ -152,10 +133,7 @@ interface IStakingExtension is IStakingData { * @param _delegator Address of the delegator * @return Delegation data */ - function getDelegation(address _indexer, address _delegator) - external - view - returns (Delegation memory); + function getDelegation(address _indexer, address _delegator) external view returns (Delegation memory); /** * @notice Return whether the delegator has delegated to the indexer. @@ -170,10 +148,7 @@ interface IStakingExtension is IStakingData { * @param _delegation Delegation of tokens from delegator to indexer * @return Amount of tokens to withdraw */ - function getWithdraweableDelegatedTokens(Delegation memory _delegation) - external - view - returns (uint256); + function getWithdraweableDelegatedTokens(Delegation memory _delegation) external view returns (uint256); /** * @notice Getter for the delegationRatio, i.e. the delegation capacity multiplier: @@ -313,8 +288,5 @@ interface IStakingExtension is IStakingData { * @param _allocationID Allocation ID for which to query the allocation information * @return The specified allocation, as an IStakingData.Allocation struct */ - function allocations(address _allocationID) - external - view - returns (IStakingData.Allocation memory); + function allocations(address _allocationID) external view returns (IStakingData.Allocation memory); } diff --git a/packages/contracts/contracts/staking/L1Staking.sol b/packages/contracts/contracts/staking/L1Staking.sol index cf9bca304..df4e145bd 100644 --- a/packages/contracts/contracts/staking/L1Staking.sol +++ b/packages/contracts/contracts/staking/L1Staking.sol @@ -31,10 +31,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { * transfer of stake/delegation for vesting lock wallets. */ receive() external payable { - require( - msg.sender == address(l1GraphTokenLockTransferTool), - "Only transfer tool can send ETH" - ); + require(msg.sender == address(l1GraphTokenLockTransferTool), "Only transfer tool can send ETH"); } /** @@ -73,19 +70,8 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { uint256 _gasPriceBid, uint256 _maxSubmissionCost ) external payable override notPartialPaused { - require( - msg.value == _maxSubmissionCost.add(_gasPriceBid.mul(_maxGas)), - "INVALID_ETH_AMOUNT" - ); - _transferStakeToL2( - msg.sender, - _l2Beneficiary, - _amount, - _maxGas, - _gasPriceBid, - _maxSubmissionCost, - msg.value - ); + require(msg.value == _maxSubmissionCost.add(_gasPriceBid.mul(_maxGas)), "INVALID_ETH_AMOUNT"); + _transferStakeToL2(msg.sender, _l2Beneficiary, _amount, _maxGas, _gasPriceBid, _maxSubmissionCost, msg.value); } /** @@ -118,15 +104,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { uint256 ethAmount = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid)); l1GraphTokenLockTransferTool.pullETH(msg.sender, ethAmount); require(address(this).balance == balance.add(ethAmount), "ETH TRANSFER FAILED"); - _transferStakeToL2( - msg.sender, - l2Beneficiary, - _amount, - _maxGas, - _gasPriceBid, - _maxSubmissionCost, - ethAmount - ); + _transferStakeToL2(msg.sender, l2Beneficiary, _amount, _maxGas, _gasPriceBid, _maxSubmissionCost, ethAmount); } /** @@ -152,10 +130,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { uint256 _gasPriceBid, uint256 _maxSubmissionCost ) external payable override notPartialPaused { - require( - msg.value == _maxSubmissionCost.add(_gasPriceBid.mul(_maxGas)), - "INVALID_ETH_AMOUNT" - ); + require(msg.value == _maxSubmissionCost.add(_gasPriceBid.mul(_maxGas)), "INVALID_ETH_AMOUNT"); _transferDelegationToL2( msg.sender, _indexer, @@ -216,11 +191,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { * and can be withdrawn with `withdrawDelegated()` immediately after calling this. * @param _indexer Address of the indexer (in L1, before transferring to L2) */ - function unlockDelegationToTransferredIndexer(address _indexer) - external - override - notPartialPaused - { + function unlockDelegationToTransferredIndexer(address _indexer) external override notPartialPaused { require( indexerTransferredToL2[_indexer] != address(0) && __stakes[_indexer].tokensStaked == 0, "indexer not transferred" @@ -269,10 +240,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { require(_l2Beneficiary != address(0), "l2Beneficiary == 0"); if (indexerTransferredToL2[_indexer] != address(0)) { - require( - indexerTransferredToL2[_indexer] == _l2Beneficiary, - "l2Beneficiary != previous" - ); + require(indexerTransferredToL2[_indexer] == _l2Beneficiary, "l2Beneficiary != previous"); } else { indexerTransferredToL2[_indexer] = _l2Beneficiary; require(_amount >= __minimumIndexerStake, "!minimumIndexerStake sent"); @@ -292,10 +260,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { } else { // require that the indexer has enough stake to cover all allocations uint256 tokensDelegatedCap = indexerStake.tokensStaked.mul(uint256(__delegationRatio)); - uint256 tokensDelegatedCapacity = MathUtils.min( - delegationPool.tokens, - tokensDelegatedCap - ); + uint256 tokensDelegatedCapacity = MathUtils.min(delegationPool.tokens, tokensDelegatedCap); require( indexerStake.tokensUsed() <= indexerStake.tokensStaked.add(tokensDelegatedCapacity), "! allocation capacity" @@ -310,14 +275,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { abi.encode(functionData) ); - _sendTokensAndMessageToL2Staking( - _amount, - _maxGas, - _gasPriceBid, - _maxSubmissionCost, - _ethAmount, - extraData - ); + _sendTokensAndMessageToL2Staking(_amount, _maxGas, _gasPriceBid, _maxSubmissionCost, _ethAmount, extraData); emit IndexerStakeTransferredToL2(_indexer, _l2Beneficiary, _amount); } @@ -369,10 +327,7 @@ contract L1Staking is Staking, L1StakingV1Storage, IL1StakingBase { IL2Staking.ReceiveDelegationData memory functionData; functionData.indexer = indexerTransferredToL2[_indexer]; functionData.delegator = _l2Beneficiary; - extraData = abi.encode( - uint8(IL2Staking.L1MessageCodes.RECEIVE_DELEGATION_CODE), - abi.encode(functionData) - ); + extraData = abi.encode(uint8(IL2Staking.L1MessageCodes.RECEIVE_DELEGATION_CODE), abi.encode(functionData)); } _sendTokensAndMessageToL2Staking( diff --git a/packages/contracts/contracts/staking/Staking.sol b/packages/contracts/contracts/staking/Staking.sol index 2139160da..e9da34440 100644 --- a/packages/contracts/contracts/staking/Staking.sol +++ b/packages/contracts/contracts/staking/Staking.sol @@ -212,12 +212,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M uint32 _lambdaNumerator, uint32 _lambdaDenominator ) external override onlyGovernor { - _setRebateParameters( - _alphaNumerator, - _alphaDenominator, - _lambdaNumerator, - _lambdaDenominator - ); + _setRebateParameters(_alphaNumerator, _alphaDenominator, _lambdaNumerator, _lambdaDenominator); } /** @@ -384,12 +379,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M // -- Collect curation fees -- // Only if the subgraph deployment is curated - curationFees = _collectCurationFees( - graphToken, - subgraphDeploymentID, - queryFees, - __curationPercentage - ); + curationFees = _collectCurationFees(graphToken, subgraphDeploymentID, queryFees, __curationPercentage); queryFees = queryFees.sub(curationFees); // -- Process rebate reward -- @@ -478,12 +468,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @param _allocationID Address used as allocation identifier * @return Allocation data */ - function getAllocation(address _allocationID) - external - view - override - returns (Allocation memory) - { + function getAllocation(address _allocationID) external view override returns (Allocation memory) { return __allocations[_allocationID]; } @@ -492,12 +477,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @param _allocationID Allocation identifier * @return AllocationState enum with the state of the allocation */ - function getAllocationState(address _allocationID) - external - view - override - returns (AllocationState) - { + function getAllocationState(address _allocationID) external view override returns (AllocationState) { return _getAllocationState(_allocationID); } @@ -506,12 +486,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @param _subgraphDeploymentID Deployment ID for the subgraph * @return Total tokens allocated to subgraph */ - function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) - external - view - override - returns (uint256) - { + function getSubgraphAllocatedTokens(bytes32 _subgraphDeploymentID) external view override returns (uint256) { return __subgraphAllocations[_subgraphDeploymentID]; } @@ -563,9 +538,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M Stakes.Indexer memory indexerStake = __stakes[_indexer]; uint256 tokensDelegated = __delegationPools[_indexer].tokens; - uint256 tokensDelegatedCap = indexerStake.tokensSecureStake().mul( - uint256(__delegationRatio) - ); + uint256 tokensDelegatedCap = indexerStake.tokensSecureStake().mul(uint256(__delegationRatio)); uint256 tokensDelegatedCapacity = MathUtils.min(tokensDelegated, tokensDelegatedCap); return indexerStake.tokensAvailableWithDelegation(tokensDelegatedCapacity); @@ -661,11 +634,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @param _indexingRewardCut Percentage of indexing rewards left for delegators * @param _queryFeeCut Percentage of query fees left for delegators */ - function _setDelegationParameters( - address _indexer, - uint32 _indexingRewardCut, - uint32 _queryFeeCut - ) internal { + function _setDelegationParameters(address _indexer, uint32 _indexingRewardCut, uint32 _queryFeeCut) internal { // Incentives must be within bounds require(_queryFeeCut <= MAX_PPM, ">queryFeeCut"); require(_indexingRewardCut <= MAX_PPM, ">indexingRewardCut"); @@ -690,10 +659,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M */ function _stake(address _indexer, uint256 _tokens) internal { // Ensure minimum stake - require( - __stakes[_indexer].tokensSecureStake().add(_tokens) >= __minimumIndexerStake, - "!minimumIndexerStake" - ); + require(__stakes[_indexer].tokensSecureStake().add(_tokens) >= __minimumIndexerStake, "!minimumIndexerStake"); // Deposit tokens into the indexer stake __stakes[_indexer].deposit(_tokens); @@ -750,10 +716,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M bytes32 digest = ECDSA.toEthSignedMessageHash(messageHash); require(ECDSA.recover(digest, _proof) == _allocationID, "!proof"); - require( - __stakes[_indexer].tokensSecureStake() >= __minimumIndexerStake, - "!minimumIndexerStake" - ); + require(__stakes[_indexer].tokensSecureStake() >= __minimumIndexerStake, "!minimumIndexerStake"); if (_tokens > 0) { // Needs to have free capacity not used for other purposes to allocate require(getIndexerCapacity(_indexer) >= _tokens, "!capacity"); @@ -784,9 +747,9 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M // Track total allocations per subgraph // Used for rewards calculations - __subgraphAllocations[alloc.subgraphDeploymentID] = __subgraphAllocations[ - alloc.subgraphDeploymentID - ].add(alloc.tokens); + __subgraphAllocations[alloc.subgraphDeploymentID] = __subgraphAllocations[alloc.subgraphDeploymentID].add( + alloc.tokens + ); } emit AllocationCreated( @@ -845,9 +808,9 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M // Track total allocations per subgraph // Used for rewards calculations - __subgraphAllocations[alloc.subgraphDeploymentID] = __subgraphAllocations[ - alloc.subgraphDeploymentID - ].sub(alloc.tokens); + __subgraphAllocations[alloc.subgraphDeploymentID] = __subgraphAllocations[alloc.subgraphDeploymentID].sub( + alloc.tokens + ); } emit AllocationClosed( @@ -869,10 +832,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @param _tokens Total tokens received used to calculate the amount of fees to collect * @return Amount of delegation rewards */ - function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) - private - returns (uint256) - { + function _collectDelegationQueryRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; DelegationPool storage pool = __delegationPools[_indexer]; if (pool.tokens > 0 && pool.queryFeeCut < MAX_PPM) { @@ -890,10 +850,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @param _tokens Total tokens received used to calculate the amount of fees to collect * @return Amount of delegation rewards */ - function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) - private - returns (uint256) - { + function _collectDelegationIndexingRewards(address _indexer, uint256 _tokens) private returns (uint256) { uint256 delegationRewards = 0; DelegationPool storage pool = __delegationPools[_indexer]; if (pool.tokens > 0 && pool.indexingRewardCut < MAX_PPM) { @@ -929,10 +886,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M if (isCurationEnabled && curation.isCurated(_subgraphDeploymentID)) { // Calculate the tokens after curation fees first, and subtact that, // to prevent curation fees from rounding down to zero - uint256 tokensAfterCurationFees = uint256(MAX_PPM) - .sub(_curationPercentage) - .mul(_tokens) - .div(MAX_PPM); + uint256 tokensAfterCurationFees = uint256(MAX_PPM).sub(_curationPercentage).mul(_tokens).div(MAX_PPM); uint256 curationFees = _tokens.sub(tokensAfterCurationFees); if (curationFees > 0) { // Transfer and call collect() @@ -954,11 +908,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M * @param _percentage Percentage of tokens to burn as tax * @return Amount of tax charged */ - function _collectTax( - IGraphToken _graphToken, - uint256 _tokens, - uint256 _percentage - ) private returns (uint256) { + function _collectTax(IGraphToken _graphToken, uint256 _tokens, uint256 _percentage) private returns (uint256) { // Calculate tokens after tax first, and subtract that, // to prevent the tax from rounding down to zero uint256 tokensAfterTax = uint256(MAX_PPM).sub(_percentage).mul(_tokens).div(MAX_PPM); @@ -1004,27 +954,17 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M uint256 indexerRewards = totalRewards.sub(delegationRewards); // Send the indexer rewards - _sendRewards( - graphToken(), - indexerRewards, - _indexer, - __rewardsDestination[_indexer] == address(0) - ); + _sendRewards(graphToken(), indexerRewards, _indexer, __rewardsDestination[_indexer] == address(0)); } /** - * @dev Send rewards to the appropiate destination. + * @dev Send rewards to the appropriate destination. * @param _graphToken Graph token * @param _amount Number of rewards tokens * @param _beneficiary Address of the beneficiary of rewards * @param _restake Whether to restake or not */ - function _sendRewards( - IGraphToken _graphToken, - uint256 _amount, - address _beneficiary, - bool _restake - ) private { + function _sendRewards(IGraphToken _graphToken, uint256 _amount, address _beneficiary, bool _restake) private { if (_amount == 0) return; if (_restake) { @@ -1033,11 +973,7 @@ abstract contract Staking is StakingV4Storage, GraphUpgradeable, IStakingBase, M } else { // Transfer funds to the beneficiary's designated rewards destination if set address destination = __rewardsDestination[_beneficiary]; - TokenUtils.pushTokens( - _graphToken, - destination == address(0) ? _beneficiary : destination, - _amount - ); + TokenUtils.pushTokens(_graphToken, destination == address(0) ? _beneficiary : destination, _amount); } } diff --git a/packages/contracts/contracts/staking/StakingExtension.sol b/packages/contracts/contracts/staking/StakingExtension.sol index 08839ca2a..ee38364b5 100644 --- a/packages/contracts/contracts/staking/StakingExtension.sol +++ b/packages/contracts/contracts/staking/StakingExtension.sol @@ -82,11 +82,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @dev This function is only callable by the governor * @param _delegationUnbondingPeriod Period in epochs to wait for token withdrawals after undelegating */ - function setDelegationUnbondingPeriod(uint32 _delegationUnbondingPeriod) - external - override - onlyGovernor - { + function setDelegationUnbondingPeriod(uint32 _delegationUnbondingPeriod) external override onlyGovernor { _setDelegationUnbondingPeriod(_delegationUnbondingPeriod); } @@ -107,12 +103,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _tokens Amount of tokens to delegate * @return Amount of shares issued from the delegation pool */ - function delegate(address _indexer, uint256 _tokens) - external - override - notPartialPaused - returns (uint256) - { + function delegate(address _indexer, uint256 _tokens) external override notPartialPaused returns (uint256) { address delegator = msg.sender; // Transfer tokens to delegate to this contract @@ -128,12 +119,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _shares Amount of shares to return and undelegate tokens * @return Amount of tokens returned for the shares of the delegation pool */ - function undelegate(address _indexer, uint256 _shares) - external - override - notPartialPaused - returns (uint256) - { + function undelegate(address _indexer, uint256 _shares) external override notPartialPaused returns (uint256) { return _undelegate(msg.sender, _indexer, _shares); } @@ -143,12 +129,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _indexer Withdraw available tokens delegated to indexer * @param _newIndexer Re-delegate to indexer address if non-zero, withdraw if zero address */ - function withdrawDelegated(address _indexer, address _newIndexer) - external - override - notPaused - returns (uint256) - { + function withdrawDelegated(address _indexer, address _newIndexer) external override notPaused returns (uint256) { return _withdrawDelegated(msg.sender, _indexer, _newIndexer); } @@ -211,12 +192,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _delegator Address of the delegator * @return Delegation data */ - function getDelegation(address _indexer, address _delegator) - external - view - override - returns (Delegation memory) - { + function getDelegation(address _indexer, address _delegator) external view override returns (Delegation memory) { return __delegationPools[_indexer].delegators[_delegator]; } @@ -254,12 +230,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _indexer Address of the indexer for which to query the delegation pool * @return Delegation pool as a DelegationPoolReturn struct */ - function delegationPools(address _indexer) - external - view - override - returns (DelegationPoolReturn memory) - { + function delegationPools(address _indexer) external view override returns (DelegationPoolReturn memory) { DelegationPool storage pool = __delegationPools[_indexer]; return DelegationPoolReturn( @@ -289,12 +260,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _maybeOperator The address that may or may not be an operator * @return True if the operator is authorized to operate on behalf of the indexer */ - function operatorAuth(address _indexer, address _maybeOperator) - external - view - override - returns (bool) - { + function operatorAuth(address _indexer, address _maybeOperator) external view override returns (bool) { return __operatorAuth[_indexer][_maybeOperator]; } @@ -304,12 +270,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _subgraphDeploymentId The subgraph deployment for which to query the allocations * @return The amount of tokens allocated to the subgraph deployment */ - function subgraphAllocations(bytes32 _subgraphDeploymentId) - external - view - override - returns (uint256) - { + function subgraphAllocations(bytes32 _subgraphDeploymentId) external view override returns (uint256) { return __subgraphAllocations[_subgraphDeploymentId]; } @@ -418,12 +379,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _allocationID Allocation ID for which to query the allocation information * @return The specified allocation, as an IStakingData.Allocation struct */ - function allocations(address _allocationID) - external - view - override - returns (IStakingData.Allocation memory) - { + function allocations(address _allocationID) external view override returns (IStakingData.Allocation memory) { return __allocations[_allocationID]; } @@ -442,12 +398,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _delegation Delegation of tokens from delegator to indexer * @return Amount of tokens to withdraw */ - function getWithdraweableDelegatedTokens(Delegation memory _delegation) - public - view - override - returns (uint256) - { + function getWithdraweableDelegatedTokens(Delegation memory _delegation) public view override returns (uint256) { // There must be locked tokens and period passed uint256 currentEpoch = epochManager().currentEpoch(); if (_delegation.tokensLockedUntil > 0 && currentEpoch >= _delegation.tokensLockedUntil) { @@ -495,11 +446,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _tokens Amount of tokens to delegate * @return Amount of shares issued of the delegation pool */ - function _delegate( - address _delegator, - address _indexer, - uint256 _tokens - ) private returns (uint256) { + function _delegate(address _delegator, address _indexer, uint256 _tokens) private returns (uint256) { // Only allow delegations over a minimum, to prevent rounding attacks require(_tokens >= MINIMUM_DELEGATION, "!minimum-delegation"); // Only delegate to non-empty address @@ -516,9 +463,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi uint256 delegatedTokens = _tokens.sub(delegationTax); // Calculate shares to issue - uint256 shares = (pool.tokens == 0) - ? delegatedTokens - : delegatedTokens.mul(pool.shares).div(pool.tokens); + uint256 shares = (pool.tokens == 0) ? delegatedTokens : delegatedTokens.mul(pool.shares).div(pool.tokens); require(shares > 0, "!shares"); // Update the delegation pool @@ -540,11 +485,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _shares Amount of shares to return and undelegate tokens * @return Amount of tokens returned for the shares of the delegation pool */ - function _undelegate( - address _delegator, - address _indexer, - uint256 _shares - ) private returns (uint256) { + function _undelegate(address _delegator, address _indexer, uint256 _shares) private returns (uint256) { // Can only undelegate a non-zero amount of shares require(_shares > 0, "!shares"); @@ -581,17 +522,9 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi require(remainingDelegation >= MINIMUM_DELEGATION, "!minimum-delegation"); } delegation.tokensLocked = delegation.tokensLocked.add(tokens); - delegation.tokensLockedUntil = epochManager().currentEpoch().add( - __delegationUnbondingPeriod - ); - - emit StakeDelegatedLocked( - _indexer, - _delegator, - tokens, - _shares, - delegation.tokensLockedUntil - ); + delegation.tokensLockedUntil = epochManager().currentEpoch().add(__delegationUnbondingPeriod); + + emit StakeDelegatedLocked(_indexer, _delegator, tokens, _shares, delegation.tokensLockedUntil); return tokens; } @@ -642,11 +575,7 @@ contract StakingExtension is StakingV4Storage, GraphUpgradeable, IStakingExtensi * @param _percentage Percentage of tokens to burn as tax * @return Amount of tax charged */ - function _collectTax( - IGraphToken _graphToken, - uint256 _tokens, - uint256 _percentage - ) private returns (uint256) { + function _collectTax(IGraphToken _graphToken, uint256 _tokens, uint256 _percentage) private returns (uint256) { uint256 tax = uint256(_percentage).mul(_tokens).div(MAX_PPM); TokenUtils.burnTokens(_graphToken, tax); // Burn tax if any return tax; diff --git a/packages/contracts/contracts/staking/libs/Exponential.sol b/packages/contracts/contracts/staking/libs/Exponential.sol index 303b6790b..c9370342e 100644 --- a/packages/contracts/contracts/staking/libs/Exponential.sol +++ b/packages/contracts/contracts/staking/libs/Exponential.sol @@ -54,10 +54,7 @@ library LibExponential { } // Compute `1 - alpha * exp ^(-exponent)` - int256 factor = LibFixedMath.sub( - LibFixedMath.one(), - LibFixedMath.mul(alpha, LibFixedMath.exp(-exponent)) - ); + int256 factor = LibFixedMath.sub(LibFixedMath.one(), LibFixedMath.mul(alpha, LibFixedMath.exp(-exponent))); // Weight the fees by the factor return LibFixedMath.uintMul(factor, fees); diff --git a/packages/contracts/contracts/staking/libs/LibFixedMath.sol b/packages/contracts/contracts/staking/libs/LibFixedMath.sol index b8e5e39a5..ae8c9b69e 100644 --- a/packages/contracts/contracts/staking/libs/LibFixedMath.sol +++ b/packages/contracts/contracts/staking/libs/LibFixedMath.sol @@ -24,24 +24,20 @@ pragma solidity ^0.7.6; /// @dev Signed, fixed-point, 127-bit precision math library. library LibFixedMath { // 1 - int256 private constant FIXED_1 = - int256(0x0000000000000000000000000000000080000000000000000000000000000000); + int256 private constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000); // 2**255 - int256 private constant MIN_FIXED_VAL = - int256(0x8000000000000000000000000000000000000000000000000000000000000000); + int256 private constant MIN_FIXED_VAL = int256(0x8000000000000000000000000000000000000000000000000000000000000000); // 1^2 (in fixed-point) int256 private constant FIXED_1_SQUARED = int256(0x4000000000000000000000000000000000000000000000000000000000000000); // 1 int256 private constant LN_MAX_VAL = FIXED_1; // e ^ -63.875 - int256 private constant LN_MIN_VAL = - int256(0x0000000000000000000000000000000000000000000000000000000733048c5a); + int256 private constant LN_MIN_VAL = int256(0x0000000000000000000000000000000000000000000000000000000733048c5a); // 0 int256 private constant EXP_MAX_VAL = 0; // -63.875 - int256 private constant EXP_MIN_VAL = - -int256(0x0000000000000000000000000000001ff0000000000000000000000000000000); + int256 private constant EXP_MIN_VAL = -int256(0x0000000000000000000000000000001ff0000000000000000000000000000000); /// @dev Get one as a fixed-point number. function one() internal pure returns (int256 f) { @@ -72,11 +68,7 @@ library LibFixedMath { } /// @dev Performs (a * n) / d, without scaling for precision. - function mulDiv( - int256 a, - int256 n, - int256 d - ) internal pure returns (int256 c) { + function mulDiv(int256 a, int256 n, int256 d) internal pure returns (int256 c) { c = _div(_mul(a, n), d); } @@ -172,65 +164,47 @@ library LibFixedMath { // e ^ -32 if (x <= int256(0x00000000000000000000000000000000000000000001c8464f76164760000000)) { r -= int256(0x0000000000000000000000000000001000000000000000000000000000000000); // - 32 - x = - (x * FIXED_1) / - int256(0x00000000000000000000000000000000000000000001c8464f76164760000000); // / e ^ -32 + x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000000001c8464f76164760000000); // / e ^ -32 } // e ^ -16 if (x <= int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000)) { r -= int256(0x0000000000000000000000000000000800000000000000000000000000000000); // - 16 - x = - (x * FIXED_1) / - int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000); // / e ^ -16 + x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000); // / e ^ -16 } // e ^ -8 if (x <= int256(0x00000000000000000000000000000000000afe10820813d78000000000000000)) { r -= int256(0x0000000000000000000000000000000400000000000000000000000000000000); // - 8 - x = - (x * FIXED_1) / - int256(0x00000000000000000000000000000000000afe10820813d78000000000000000); // / e ^ -8 + x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000afe10820813d78000000000000000); // / e ^ -8 } // e ^ -4 if (x <= int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000)) { r -= int256(0x0000000000000000000000000000000200000000000000000000000000000000); // - 4 - x = - (x * FIXED_1) / - int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000); // / e ^ -4 + x = (x * FIXED_1) / int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000); // / e ^ -4 } // e ^ -2 if (x <= int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000)) { r -= int256(0x0000000000000000000000000000000100000000000000000000000000000000); // - 2 - x = - (x * FIXED_1) / - int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000); // / e ^ -2 + x = (x * FIXED_1) / int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000); // / e ^ -2 } // e ^ -1 if (x <= int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000)) { r -= int256(0x0000000000000000000000000000000080000000000000000000000000000000); // - 1 - x = - (x * FIXED_1) / - int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000); // / e ^ -1 + x = (x * FIXED_1) / int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000); // / e ^ -1 } // e ^ -0.5 if (x <= int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000)) { r -= int256(0x0000000000000000000000000000000040000000000000000000000000000000); // - 0.5 - x = - (x * FIXED_1) / - int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000); // / e ^ -0.5 + x = (x * FIXED_1) / int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000); // / e ^ -0.5 } // e ^ -0.25 if (x <= int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000)) { r -= int256(0x0000000000000000000000000000000020000000000000000000000000000000); // - 0.25 - x = - (x * FIXED_1) / - int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000); // / e ^ -0.25 + x = (x * FIXED_1) / int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000); // / e ^ -0.25 } // e ^ -0.125 if (x <= int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) { r -= int256(0x0000000000000000000000000000000010000000000000000000000000000000); // - 0.125 - x = - (x * FIXED_1) / - int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d); // / e ^ -0.125 + x = (x * FIXED_1) / int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d); // / e ^ -0.125 } // `x` is now our residual in the range of 1 <= x <= 2 (or close enough). diff --git a/packages/contracts/contracts/staking/libs/MathUtils.sol b/packages/contracts/contracts/staking/libs/MathUtils.sol index 4194b6da8..0fb20389a 100644 --- a/packages/contracts/contracts/staking/libs/MathUtils.sol +++ b/packages/contracts/contracts/staking/libs/MathUtils.sol @@ -14,19 +14,20 @@ library MathUtils { /** * @dev Calculates the weighted average of two values pondering each of these * values based on configured weights. The contribution of each value N is - * weightN/(weightA + weightB). + * weightN/(weightA + weightB). The calculation rounds up to ensure the result + * is always greater than the smallest of the two values. * @param valueA The amount for value A * @param weightA The weight to use for value A * @param valueB The amount for value B * @param weightB The weight to use for value B */ - function weightedAverage( + function weightedAverageRoundingUp( uint256 valueA, uint256 weightA, uint256 valueB, uint256 weightB ) internal pure returns (uint256) { - return valueA.mul(weightA).add(valueB.mul(weightB)).div(weightA.add(weightB)); + return valueA.mul(weightA).add(valueB.mul(weightB)).add(weightA.add(weightB).sub(1)).div(weightA.add(weightB)); } /** diff --git a/packages/contracts/contracts/staking/libs/Stakes.sol b/packages/contracts/contracts/staking/libs/Stakes.sol index 5882944d8..b0524b14c 100644 --- a/packages/contracts/contracts/staking/libs/Stakes.sol +++ b/packages/contracts/contracts/staking/libs/Stakes.sol @@ -65,15 +65,11 @@ library Stakes { * @param _tokens Amount of tokens to unstake * @param _period Period in blocks that need to pass before withdrawal */ - function lockTokens( - Stakes.Indexer storage stake, - uint256 _tokens, - uint256 _period - ) internal { + function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal { // Take into account period averaging for multiple unstake requests uint256 lockingPeriod = _period; if (stake.tokensLocked > 0) { - lockingPeriod = MathUtils.weightedAverage( + lockingPeriod = MathUtils.weightedAverageRoundingUp( MathUtils.diffOrZero(stake.tokensLockedUntil, block.number), // Remaining thawing period stake.tokensLocked, // Weighted by remaining unstaked tokens _period, // Thawing period @@ -158,11 +154,10 @@ library Stakes { * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability * @return Token amount */ - function tokensAvailableWithDelegation(Stakes.Indexer memory stake, uint256 _delegatedCapacity) - internal - pure - returns (uint256) - { + function tokensAvailableWithDelegation( + Stakes.Indexer memory stake, + uint256 _delegatedCapacity + ) internal pure returns (uint256) { uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity); uint256 _tokensUsed = stake.tokensUsed(); // If more tokens are used than the current capacity, the indexer is overallocated. diff --git a/packages/contracts/contracts/tests/CallhookReceiverMock.sol b/packages/contracts/contracts/tests/CallhookReceiverMock.sol index 1e71cf86f..e2418f3c8 100644 --- a/packages/contracts/contracts/tests/CallhookReceiverMock.sol +++ b/packages/contracts/contracts/tests/CallhookReceiverMock.sol @@ -18,11 +18,7 @@ contract CallhookReceiverMock is ICallhookReceiver { * @param _amount Amount of tokens that were transferred * @param _data ABI-encoded callhook data */ - function onTokenTransfer( - address _from, - uint256 _amount, - bytes calldata _data - ) external override { + function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override { uint256 foo; uint256 bar; (foo, bar) = abi.decode(_data, (uint256, uint256)); diff --git a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol index 2dcb6e53a..f540b1b96 100644 --- a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol +++ b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolBadMock.sol @@ -12,10 +12,7 @@ contract L1GraphTokenLockTransferToolBadMock { // Sends 1 wei less than requested function pullETH(address _l1Wallet, uint256 _amount) external { - require( - l2WalletAddress[_l1Wallet] != address(0), - "L1GraphTokenLockTransferToolMock: unknown L1 wallet" - ); + require(l2WalletAddress[_l1Wallet] != address(0), "L1GraphTokenLockTransferToolMock: unknown L1 wallet"); (bool success, ) = payable(msg.sender).call{ value: _amount - 1 }(""); require(success, "L1GraphTokenLockTransferToolMock: ETH pull failed"); } diff --git a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol index 7a786beed..a1321d62f 100644 --- a/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol +++ b/packages/contracts/contracts/tests/L1GraphTokenLockTransferToolMock.sol @@ -11,10 +11,7 @@ contract L1GraphTokenLockTransferToolMock { } function pullETH(address _l1Wallet, uint256 _amount) external { - require( - l2WalletAddress[_l1Wallet] != address(0), - "L1GraphTokenLockTransferToolMock: unknown L1 wallet" - ); + require(l2WalletAddress[_l1Wallet] != address(0), "L1GraphTokenLockTransferToolMock: unknown L1 wallet"); (bool success, ) = payable(msg.sender).call{ value: _amount }(""); require(success, "L1GraphTokenLockTransferToolMock: ETH pull failed"); } diff --git a/packages/contracts/contracts/tests/LegacyGNSMock.sol b/packages/contracts/contracts/tests/LegacyGNSMock.sol index 0e1e94be4..b2b4088b9 100644 --- a/packages/contracts/contracts/tests/LegacyGNSMock.sol +++ b/packages/contracts/contracts/tests/LegacyGNSMock.sol @@ -28,11 +28,7 @@ contract LegacyGNSMock is L1GNS { * @param subgraphID Subgraph ID * @return subgraphDeploymentID Subgraph deployment ID */ - function getSubgraphDeploymentID(uint256 subgraphID) - external - view - returns (bytes32 subgraphDeploymentID) - { + function getSubgraphDeploymentID(uint256 subgraphID) external view returns (bytes32 subgraphDeploymentID) { IGNS.SubgraphData storage subgraph = _getSubgraphData(subgraphID); subgraphDeploymentID = subgraph.subgraphDeploymentID; } diff --git a/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol b/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol index 4f2848288..77be89b4e 100644 --- a/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol +++ b/packages/contracts/contracts/tests/arbitrum/BridgeMock.sol @@ -33,14 +33,7 @@ contract BridgeMock is IBridge { ) external payable override returns (uint256) { messageIndex = messageIndex + 1; inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash))); - emit MessageDelivered( - messageIndex, - inboxAccs[messageIndex - 1], - msg.sender, - _kind, - _sender, - _messageDataHash - ); + emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash); return messageIndex; } diff --git a/packages/contracts/contracts/tests/arbitrum/InboxMock.sol b/packages/contracts/contracts/tests/arbitrum/InboxMock.sol index b600ec3ac..57af6941c 100644 --- a/packages/contracts/contracts/tests/arbitrum/InboxMock.sol +++ b/packages/contracts/contracts/tests/arbitrum/InboxMock.sol @@ -171,11 +171,7 @@ contract InboxMock is IInbox { * @param _messageData Encoded message data * @return Message number returned by the bridge */ - function _deliverMessage( - uint8 _kind, - address _sender, - bytes memory _messageData - ) internal returns (uint256) { + function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) { uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData)); emit InboxMessageDelivered(msgNum, _messageData); return msgNum; @@ -188,11 +184,7 @@ contract InboxMock is IInbox { * @param _messageDataHash keccak256 hash of the encoded message data * @return Message number returned by the bridge */ - function deliverToBridge( - uint8 _kind, - address _sender, - bytes32 _messageDataHash - ) internal returns (uint256) { + function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) { return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash); } } diff --git a/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol b/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol index a529a975a..92b9bb246 100644 --- a/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol +++ b/packages/contracts/contracts/tests/arbitrum/OutboxMock.sol @@ -136,11 +136,7 @@ contract OutboxMock is IOutbox { * @param _amount Callvalue for the function call * @param _data Calldata for the function call */ - function executeBridgeCall( - address _destAddr, - uint256 _amount, - bytes memory _data - ) internal { + function executeBridgeCall(address _destAddr, uint256 _amount, bytes memory _data) internal { (bool success, bytes memory returndata) = bridge.executeCall(_destAddr, _amount, _data); if (!success) { if (returndata.length > 0) { diff --git a/packages/contracts/contracts/tests/ens/IENS.sol b/packages/contracts/contracts/tests/ens/IENS.sol index 9de0b357c..f03cb651c 100644 --- a/packages/contracts/contracts/tests/ens/IENS.sol +++ b/packages/contracts/contracts/tests/ens/IENS.sol @@ -5,11 +5,5 @@ interface IENS { function owner(bytes32 node) external view returns (address); // Must call setRecord, not setOwner, We must namehash it ourselves as well - function setSubnodeRecord( - bytes32 node, - bytes32 label, - address owner, - address resolver, - uint64 ttl - ) external; + function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external; } diff --git a/packages/contracts/contracts/tests/ens/IPublicResolver.sol b/packages/contracts/contracts/tests/ens/IPublicResolver.sol index 7f0676837..06ce2243b 100644 --- a/packages/contracts/contracts/tests/ens/IPublicResolver.sol +++ b/packages/contracts/contracts/tests/ens/IPublicResolver.sol @@ -4,9 +4,5 @@ pragma solidity ^0.7.6; interface IPublicResolver { function text(bytes32 node, string calldata key) external view returns (string memory); - function setText( - bytes32 node, - string calldata key, - string calldata value - ) external; + function setText(bytes32 node, string calldata key, string calldata value) external; } diff --git a/packages/contracts/contracts/token/GraphToken.sol b/packages/contracts/contracts/token/GraphToken.sol index 2b354e57c..53496b9a5 100644 --- a/packages/contracts/contracts/token/GraphToken.sol +++ b/packages/contracts/contracts/token/GraphToken.sol @@ -29,17 +29,12 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-of-domainseparator bytes32 private constant DOMAIN_TYPE_HASH = - keccak256( - "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)" - ); + keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract,bytes32 salt)"); bytes32 private constant DOMAIN_NAME_HASH = keccak256("Graph Token"); bytes32 private constant DOMAIN_VERSION_HASH = keccak256("0"); - bytes32 private constant DOMAIN_SALT = - 0x51f3d585afe6dfeb2af01bba0889a36c1db03beec88c6a4d0c53817069026afa; // Randomly generated salt + bytes32 private constant DOMAIN_SALT = 0x51f3d585afe6dfeb2af01bba0889a36c1db03beec88c6a4d0c53817069026afa; // Randomly generated salt bytes32 private constant PERMIT_TYPEHASH = - keccak256( - "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" - ); + keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); // -- State -- @@ -106,9 +101,7 @@ contract GraphToken is Governed, ERC20, ERC20Burnable { abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, - keccak256( - abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, nonces[_owner], _deadline) - ) + keccak256(abi.encode(PERMIT_TYPEHASH, _owner, _spender, _value, nonces[_owner], _deadline)) ) ); nonces[_owner] = nonces[_owner].add(1); diff --git a/packages/contracts/contracts/upgrades/GraphProxy.sol b/packages/contracts/contracts/upgrades/GraphProxy.sol index d3f6eacec..7d227b065 100644 --- a/packages/contracts/contracts/upgrades/GraphProxy.sol +++ b/packages/contracts/contracts/upgrades/GraphProxy.sol @@ -47,13 +47,8 @@ contract GraphProxy is GraphProxyStorage, IGraphProxy { */ constructor(address _impl, address _admin) { assert(ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)); - assert( - IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1) - ); - assert( - PENDING_IMPLEMENTATION_SLOT == - bytes32(uint256(keccak256("eip1967.proxy.pendingImplementation")) - 1) - ); + assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); + assert(PENDING_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.pendingImplementation")) - 1)); _setAdmin(_admin); _setPendingImplementation(_impl); diff --git a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol index d96dbd449..7d809d5ec 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyAdmin.sol @@ -86,10 +86,7 @@ contract GraphProxyAdmin is Governed { * @param _implementation Address of the implementation accepting the proxy. * @param _proxy Address of the proxy being accepted. */ - function acceptProxy(GraphUpgradeable _implementation, IGraphProxy _proxy) - external - onlyGovernor - { + function acceptProxy(GraphUpgradeable _implementation, IGraphProxy _proxy) external onlyGovernor { _implementation.acceptProxy(_proxy); } diff --git a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol index b308c0a0c..05b922647 100644 --- a/packages/contracts/contracts/upgrades/GraphProxyStorage.sol +++ b/packages/contracts/contracts/upgrades/GraphProxyStorage.sol @@ -14,8 +14,7 @@ abstract contract GraphProxyStorage { * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ - bytes32 internal constant IMPLEMENTATION_SLOT = - 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Storage slot with the address of the pending implementation. @@ -30,8 +29,7 @@ abstract contract GraphProxyStorage { * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ - bytes32 internal constant ADMIN_SLOT = - 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; + bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Emitted when pendingImplementation is changed. @@ -45,10 +43,7 @@ abstract contract GraphProxyStorage { * @dev Emitted when pendingImplementation is accepted, * which means contract implementation is updated. */ - event ImplementationUpdated( - address indexed oldImplementation, - address indexed newImplementation - ); + event ImplementationUpdated(address indexed oldImplementation, address indexed newImplementation); /** * @dev Emitted when the admin account has changed. diff --git a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol index 92ce80ad7..862f7e7d5 100644 --- a/packages/contracts/contracts/upgrades/GraphUpgradeable.sol +++ b/packages/contracts/contracts/upgrades/GraphUpgradeable.sol @@ -14,8 +14,7 @@ abstract contract GraphUpgradeable { * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ - bytes32 internal constant IMPLEMENTATION_SLOT = - 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev Check if the caller is the proxy admin. @@ -60,10 +59,7 @@ abstract contract GraphUpgradeable { * @param _proxy Proxy to accept * @param _data Calldata for the initialization function call (including selector) */ - function acceptProxyAndCall(IGraphProxy _proxy, bytes calldata _data) - external - onlyProxyAdmin(_proxy) - { + function acceptProxyAndCall(IGraphProxy _proxy, bytes calldata _data) external onlyProxyAdmin(_proxy) { _proxy.acceptUpgradeAndCall(_data); } } diff --git a/packages/contracts/contracts/utils/TokenUtils.sol b/packages/contracts/contracts/utils/TokenUtils.sol index cbb23ce97..265f918a5 100644 --- a/packages/contracts/contracts/utils/TokenUtils.sol +++ b/packages/contracts/contracts/utils/TokenUtils.sol @@ -11,11 +11,7 @@ library TokenUtils { * @param _from Address sending the tokens * @param _amount Amount of tokens to transfer */ - function pullTokens( - IGraphToken _graphToken, - address _from, - uint256 _amount - ) internal { + function pullTokens(IGraphToken _graphToken, address _from, uint256 _amount) internal { if (_amount > 0) { require(_graphToken.transferFrom(_from, address(this), _amount), "!transfer"); } @@ -27,11 +23,7 @@ library TokenUtils { * @param _to Address receiving the tokens * @param _amount Amount of tokens to transfer */ - function pushTokens( - IGraphToken _graphToken, - address _to, - uint256 _amount - ) internal { + function pushTokens(IGraphToken _graphToken, address _to, uint256 _amount) internal { if (_amount > 0) { require(_graphToken.transfer(_to, _amount), "!transfer"); } diff --git a/packages/contracts/eslint.config.js b/packages/contracts/eslint.config.js new file mode 100644 index 000000000..c7c0ba1b2 --- /dev/null +++ b/packages/contracts/eslint.config.js @@ -0,0 +1,17 @@ +const config = require('eslint-graph-config') + +module.exports = [ + ...config.default, + { + rules: { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + }, + }, + { + ignores: ['**/reports/*'], + }, +] diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index 31d086727..b90eb1290 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -28,10 +28,10 @@ const SKIP_LOAD = process.env.SKIP_LOAD === 'true' function loadTasks() { require('@graphprotocol/sdk/gre') - ;['contracts', 'bridge', 'deployment', 'verify', 'e2e'].forEach((folder) => { + ;['contract', 'bridge', 'deployment', 'migrate', 'verify', 'e2e'].forEach((folder) => { const tasksPath = path.join(__dirname, 'tasks', folder) fs.readdirSync(tasksPath) - .filter((pth) => pth.includes('.ts')) + .filter(pth => pth.includes('.ts')) .forEach((task) => { require(`${tasksPath}/${task}`) }) @@ -110,16 +110,16 @@ function setupNetworkProviders(hardhatConfig) { // Config -const DEFAULT_TEST_MNEMONIC = - 'myth like bonus scare over problem client lizard pioneer submit female collect' +const DEFAULT_TEST_MNEMONIC + = 'myth like bonus scare over problem client lizard pioneer submit female collect' -const DEFAULT_L2_TEST_MNEMONIC = - 'urge never interest human any economy gentle canvas anxiety pave unlock find' +const DEFAULT_L2_TEST_MNEMONIC + = 'urge never interest human any economy gentle canvas anxiety pave unlock find' const config: HardhatUserConfig = { paths: { sources: './contracts', - tests: './test', + tests: './test/unit', artifacts: './build/contracts', }, solidity: { @@ -162,6 +162,8 @@ const config: HardhatUserConfig = { url: 'http://127.0.0.1:8545', accounts: process.env.FORK === 'true' ? getAccountsKeys() : { mnemonic: DEFAULT_TEST_MNEMONIC }, + graphConfig: 'config/graph.localhost.yml', + addressBook: 'addresses-local.json', }, localnitrol1: { chainId: 1337, @@ -178,8 +180,8 @@ const config: HardhatUserConfig = { }, graph: { addressBook: process.env.ADDRESS_BOOK ?? 'addresses.json', - l1GraphConfig: process.env.L1_GRAPH_CONFIG ?? 'config/graph.localhost.yml', - l2GraphConfig: process.env.L2_GRAPH_CONFIG ?? 'config/graph.arbitrum-localhost.yml', + l1GraphConfig: process.env.L1_GRAPH_CONFIG ?? 'config/graph.mainnet.yml', + l2GraphConfig: process.env.L2_GRAPH_CONFIG ?? 'config/graph.arbitrum-one.yml', fork: process.env.FORK === 'true', disableSecureAccounts: process.env.DISABLE_SECURE_ACCOUNTS === 'true', }, @@ -231,8 +233,8 @@ const config: HardhatUserConfig = { disambiguatePaths: false, }, defender: { - apiKey: process.env.DEFENDER_API_KEY!, - apiSecret: process.env.DEFENDER_API_SECRET!, + apiKey: process.env.DEFENDER_API_KEY, + apiSecret: process.env.DEFENDER_API_SECRET, }, } diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 3b2d95896..4e95a8f3c 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@graphprotocol/contracts", - "version": "6.0.0", + "version": "6.2.1", "description": "Contracts for the Graph Protocol", "directories": { "test": "test" @@ -13,11 +13,11 @@ "addresses.json" ], "dependencies": { - "@graphprotocol/sdk": "workspace:^0.3.0", + "@graphprotocol/sdk": "workspace:^0.5.0", "console-table-printer": "^2.11.1" }, "devDependencies": { - "@arbitrum/sdk": "^3.0.0", + "@arbitrum/sdk": "~3.1.13", "@defi-wonderland/smock": "^2.0.7", "@ethersproject/experimental": "^5.6.0", "@graphprotocol/common-ts": "^1.8.3", @@ -42,8 +42,6 @@ "@types/sinon-chai": "^3.2.12", "@types/winston": "^2.4.4", "@types/yargs": "^16.0.0", - "@typescript-eslint/eslint-plugin": "^4.0.0", - "@typescript-eslint/parser": "^4.0.0", "@urql/core": "^2.1.3", "arbos-precompiles": "^1.0.2", "bignumber.js": "^9.0.0", @@ -51,10 +49,8 @@ "chai-as-promised": "^7.1.1", "cli-table": "^0.3.6", "dotenv": "^9.0.0", - "eslint": "^7.24.0", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-no-only-tests": "^2.4.0", - "eslint-plugin-prettier": "^3.4.0", + "eslint": "^8.57.0", + "eslint-graph-config": "workspace:^0.0.1", "ethereum-waffle": "^3.2.0", "ethers": "^5.7.2", "form-data": "^4.0.0", @@ -72,10 +68,10 @@ "isomorphic-fetch": "^3.0.0", "lint-staged": "^10.5.4", "p-queue": "^6.6.1", - "prettier": "^2.2.1", - "prettier-plugin-solidity": "1.0.0-beta.19", - "solhint": "^3.3.6", - "solhint-plugin-prettier": "^0.0.5", + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1", + "solhint": "^4.1.1", + "solhint-graph-config": "workspace:^0.0.1", "solidity-coverage": "^0.7.16", "ts-node": "^10.9.1", "typechain": "^5.0.0", @@ -85,14 +81,12 @@ "yargs": "^17.0.0" }, "scripts": { - "prepublishOnly": "scripts/prepublish", + "prepack": "scripts/prepack", "build": "SKIP_LOAD=true scripts/build", "clean": "rm -rf build/ cache/ dist/", "compile": "hardhat compile", - "deploy": "yarn predeploy && yarn build && yarn predeploy && hardhat migrate", - "deploy-localhost": "yarn deploy --force --network localhost --graph-config config/graph.localhost.yml", - "deploy-goerli": "yarn deploy --force --network goerli --graph-config config/graph.goerli.yml", - "deploy-arbitrum-goerli": "yarn deploy --force --network arbitrum-goerli --graph-config config/graph.arbitrum-goerli.yml", + "deploy": "yarn predeploy && yarn build && hardhat migrate", + "deploy-localhost": "yarn build && hardhat migrate --force --skip-confirmation --disable-secure-accounts --network localhost --graph-config config/graph.localhost.yml --address-book addresses-local.json", "predeploy": "scripts/predeploy", "test": "scripts/test", "test:e2e": "scripts/e2e", @@ -100,14 +94,8 @@ "test:coverage": "scripts/coverage", "test:upgrade": "scripts/upgrade", "lint": "yarn lint:ts && yarn lint:sol", - "lint:fix": "yarn lint:ts:fix && yarn lint:sol:fix", - "lint:ts": "eslint '**/*.{js,ts}'", - "lint:ts:fix": "yarn prettier:ts && eslint '**/*.{js,ts}' --fix", - "lint:sol": "solhint 'contracts/**/*.sol'", - "lint:sol:fix": "yarn prettier:sol && solhint --fix 'contracts/**/*.sol'", - "prettier": "yarn prettier:ts && yarn prettier:sol", - "prettier:ts": "prettier --write '**/*.{js,ts,json}'", - "prettier:sol": "prettier --write 'contracts/**/*.sol'", + "lint:ts": "eslint '**/*.{js,ts}' --fix", + "lint:sol": "prettier --write 'contracts/**/*.sol' && solhint --fix --noPrompt contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", "analyze": "scripts/analyze", "myth": "scripts/myth", "flatten": "scripts/flatten && scripts/clean", @@ -117,16 +105,16 @@ }, "lint-staged": { "contracts/**/*.sol": [ - "yarn lint:sol:fix" + "yarn lint:sol" ], "**/*.ts": [ - "yarn lint:ts:fix" + "yarn lint:ts" ], "**/*.js": [ - "yarn lint:ts:fix" + "yarn lint:ts" ], "**/*.json": [ - "yarn lint:ts:fix" + "yarn lint:ts" ] }, "repository": { diff --git a/packages/contracts/prettier.config.js b/packages/contracts/prettier.config.js new file mode 100644 index 000000000..5b8e866f2 --- /dev/null +++ b/packages/contracts/prettier.config.js @@ -0,0 +1,2 @@ +const prettierGraphConfig = require('solhint-graph-config/prettier') +module.exports = prettierGraphConfig diff --git a/packages/contracts/scripts/clean b/packages/contracts/scripts/clean index c84dd2aa8..28becb233 100755 --- a/packages/contracts/scripts/clean +++ b/packages/contracts/scripts/clean @@ -8,7 +8,6 @@ echo "Cleaning flattened contracts..." FLATTENED_FILES=( "$OUT_DIR/Controller.sol" - "$OUT_DIR/GraphGovernance.sol" "$OUT_DIR/GNS.sol" "$OUT_DIR/ServiceRegistry.sol" "$OUT_DIR/Curation.sol" @@ -27,4 +26,4 @@ for path in ${FLATTENED_FILES[@]}; do -e "s|// SPDX-License-Identifier:.*||g" \ -e 's|pragma abicoder v2;|//pragma abicoder v2;|g' \ -e '1s|^|pragma abicoder v2;\n|' $path -done \ No newline at end of file +done diff --git a/packages/contracts/scripts/e2e b/packages/contracts/scripts/e2e index 9e05af5d4..5622101bd 100755 --- a/packages/contracts/scripts/e2e +++ b/packages/contracts/scripts/e2e @@ -45,23 +45,17 @@ if [[ "$L1_NETWORK" == "$L2_NETWORK" ]]; then fi ### > SCRIPT AUX FUNCTIONS < -function pre_deploy() { +function deploy() { local NETWORK=$1 local GRAPH_CONFIG=$2 - - # Create named accounts - npx hardhat migrate:accounts --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --disable-secure-accounts - + local ADDRESS_BOOK=$3 + + echo "Deploying protocol on $NETWORK" + # Fund accounts if using nitro test nodes if [[ "$NETWORK" == *"localnitro"* ]]; then - npx hardhat nitro:fund-accounts --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --disable-secure-accounts + npx hardhat migrate:nitro:fund-accounts --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --disable-secure-accounts fi -} - -function deploy() { - local NETWORK=$1 - local GRAPH_CONFIG=$2 - local ADDRESS_BOOK=$3 # Deploy protocol npx hardhat migrate \ @@ -73,18 +67,6 @@ function deploy() { --address-book "$ADDRESS_BOOK" } -function post_deploy () { - local NETWORK=$1 - local GRAPH_CONFIG=$2 - local ADDRESS_BOOK=$3 - - # Governor to accept contracts ownership - npx hardhat migrate:ownership --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --disable-secure-accounts - - # Unpause the protocol - npx hardhat migrate:unpause:protocol --network "$NETWORK" --graph-config "$GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --disable-secure-accounts -} - function configure_bridge () { local L1_NETWORK=$1 local L1_GRAPH_CONFIG=$2 @@ -94,29 +76,12 @@ function configure_bridge () { local ARBITRUM_ADDRESS_BOOK=$6 local ARBITRUM_DEPLOYMENT_FILE=$7 - # These settings are only used for CLI bridge commands - # so we keep them here to avoid confusion with hardhat based tasks - local L1_CHAIN_ID=${L1_CHAIN_ID:-"1337"} - local L2_CHAIN_ID=${L2_CHAIN_ID:-"412346"} - - local L1_RPC=${L1_RPC:-"http://127.0.0.1:8545"} - local L2_RPC=${L2_RPC:-"http://127.0.0.1:8547"} - - local L1_MNEMONIC=${L1_MNEMONIC:-"myth like bonus scare over problem client lizard pioneer submit female collect"} - local L2_MNEMONIC=${L2_MNEMONIC:-"urge never interest human any economy gentle canvas anxiety pave unlock find"} - # Copy required arbitrum contract addresses to the local arbitrum address book if [[ "$L1_NETWORK" == *"localnitro"* ]]; then - npx hardhat nitro:address-book-setup --deployment-file "$ARBITRUM_DEPLOYMENT_FILE" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" + npx hardhat migrate:nitro:address-book --deployment-file "$ARBITRUM_DEPLOYMENT_FILE" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" fi - # Configure the bridge - npx hardhat bridge:configure:l1 --network "$L1_NETWORK" --graph-config "$L1_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" --disable-secure-accounts - npx hardhat bridge:configure:l2 --network "$L2_NETWORK" --graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" --disable-secure-accounts - - # Unpause the bridge - npx hardhat migrate:unpause:bridge --network "$L2_NETWORK" --graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --disable-secure-accounts - npx hardhat migrate:unpause:bridge --network "$L1_NETWORK" --graph-config "$L1_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --disable-secure-accounts + npx hardhat migrate:bridge --network "$L1_NETWORK" --l1-graph-config "$L1_GRAPH_CONFIG" --l2-graph-config "$L2_GRAPH_CONFIG" --address-book "$ADDRESS_BOOK" --arbitrum-address-book "$ARBITRUM_ADDRESS_BOOK" --disable-secure-accounts } function test_e2e () { @@ -188,18 +153,12 @@ fi ## DEPLOY # Deploy L1 if [[ -n "$L1_NETWORK" ]]; then - echo "Deploying L1 protocol" - pre_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" - post_deploy "$L1_NETWORK" "$L1_GRAPH_CONFIG" "$ADDRESS_BOOK" fi # Deploy L2 if [[ -n "$L2_NETWORK" ]]; then - echo "Deploying L2 protocol" - pre_deploy "$L2_NETWORK" "$L2_GRAPH_CONFIG" deploy "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" - post_deploy "$L2_NETWORK" "$L2_GRAPH_CONFIG" "$ADDRESS_BOOK" fi # Configure bridge diff --git a/packages/contracts/scripts/flatten b/packages/contracts/scripts/flatten index fcfbc99ab..da0eb50e1 100755 --- a/packages/contracts/scripts/flatten +++ b/packages/contracts/scripts/flatten @@ -8,7 +8,6 @@ echo "Flattening contracts..." FILES=( "contracts/governance/Controller.sol" - "contracts/governance/GraphGovernance.sol" "contracts/discovery/GNS.sol" "contracts/discovery/ServiceRegistry.sol" "contracts/curation/Curation.sol" diff --git a/packages/contracts/scripts/ops/20240208-migrate-legacy-subgraphs/data.json b/packages/contracts/scripts/ops/20240208-migrate-legacy-subgraphs/data.json new file mode 100644 index 000000000..9ec23ad5b --- /dev/null +++ b/packages/contracts/scripts/ops/20240208-migrate-legacy-subgraphs/data.json @@ -0,0 +1,342 @@ +{ + "data": { + "subgraphs": [ + { + "id": "HXFFyPyPtUrBC78p2bntnQu7rXPKo79GA5wQQ2YxLtTE", + "owner": { + "id": "0x4bb4c1b0745ef7b4642feeccd0740dec417ca0a0" + }, + "subgraphNumber": "3", + "metadataHash": "0x8cf2627713b50bce6551ad0451f73517cf731431daecd557114cc3cd6d0e1a4a" + }, + { + "id": "2Kr8drrtxmCN7vbpD6NYHSkNTNBv5pQRVtSNi4m4UvRF", + "owner": { + "id": "0xbeb1faa6e7e39c7d9bdab03a7a362fe9d73d7c61" + }, + "subgraphNumber": "0", + "metadataHash": "0x0c4b3bea53d0f01dd74d57ce5408aaadba15df4077cc3dc38085dd3796eeda03" + }, + { + "id": "2qdAX71bB2DfXbNKgpTv3b5gY4EnfYNQVpL71o7e7nEz", + "owner": { + "id": "0xefe232372e2e30951fa90d7a800d5938eedc935d" + }, + "subgraphNumber": "0", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "ba7J1xjrWGhVk5Hbonf42Fv6B9MZdzs6pN3nzeRfYzY", + "owner": { + "id": "0xadafc1e419d03c84661b00c022ecd0101f190172" + }, + "subgraphNumber": "0", + "metadataHash": "0xc0e9a91e403be87c55494a6e74f493a3da829cc9cd0bc603472212cb68641f3b" + }, + { + "id": "HJxHihBy3o1na3FDuMBPXL9ytwgP64wu3wDWZGWst3w2", + "owner": { + "id": "0x33d0d63a1f0da691b283aedd29875afeaf98e6ba" + }, + "subgraphNumber": "1", + "metadataHash": "0x2f44901f32e2d14363a5237687b8daa8e724e359df8378e997c84f1c387bc32d" + }, + { + "id": "Druh8CtrwDPwwWNdG2FPEZUeR3XP39BzvJ6QW2cZUX1N", + "owner": { + "id": "0x9f9b34c201efe888b02fdcab52422199957a0407" + }, + "subgraphNumber": "1", + "metadataHash": "0x2f44901f32e2d14363a5237687b8daa8e724e359df8378e997c84f1c387bc32d" + }, + { + "id": "DncWyiEVwDE7RDgDgbWupaqwLvnKC78xHVyRCc6Ys6M4", + "owner": { + "id": "0x33d0d63a1f0da691b283aedd29875afeaf98e6ba" + }, + "subgraphNumber": "0", + "metadataHash": "0x2f44901f32e2d14363a5237687b8daa8e724e359df8378e997c84f1c387bc32d" + }, + { + "id": "6N1FHPcJ1sQCBzmWrrNntLibGRvGHJiWWFRY7LJcmtHJ", + "owner": { + "id": "0x9f9b34c201efe888b02fdcab52422199957a0407" + }, + "subgraphNumber": "0", + "metadataHash": "0x2f44901f32e2d14363a5237687b8daa8e724e359df8378e997c84f1c387bc32d" + }, + { + "id": "okz4sT96je97dMiAJtPYmkBwDN9rov9mcMYTPskGtrq", + "owner": { + "id": "0x534a9ac3d3401f80800375680bded6a84137d296" + }, + "subgraphNumber": "4", + "metadataHash": "0xff8e9977885ae9aad139fcb0eefe78ab66ff374f86d491e878006c7d2a1c0070" + }, + { + "id": "HNWN5ymGqWGpvBbYFRyebhdGeSac3CDEssY3dpoMKgdK", + "owner": { + "id": "0xa508c16666c5b8981fa46eb32784fccc01942a71" + }, + "subgraphNumber": "0", + "metadataHash": "0xbf9b4090ff738cb433e532263065756284dc57c4092ef377f52a445e3322976d" + }, + { + "id": "Gv1rewdMuEeDQ9sWsWMjJfwKWrTxo5e19vgxr1br7Ut4", + "owner": { + "id": "0x673b6e9fe607f6ddf4a4f25b386b846c5c82995e" + }, + "subgraphNumber": "0", + "metadataHash": "0xddb85d0e63098b79b4340052b866c4d8eb638a81d74c6e135c979d23f4d1e93f" + }, + { + "id": "GNpbzUsp352dYJwP7jEL7yRJqA7uf4zfoLAHk5PiMMJu", + "owner": { + "id": "0xde0c83462a75036b74928865941b97d83a4bc994" + }, + "subgraphNumber": "0", + "metadataHash": "0x67e55fbda97b73cdb4a92f475568f27f054c6e97e8286c51256a79df9d3eb826" + }, + { + "id": "Fzw1DXaBaSeBAqg4R6qa8KZDTp7j1jpNhfAP9fpHkCGb", + "owner": { + "id": "0x9e795fc1c644ecad8031ed52856fd64b65a678ac" + }, + "subgraphNumber": "0", + "metadataHash": "0xa035f76b2dc73756a5209382a1fbf22fc714027d687439a478f7e1d38aba22ec" + }, + { + "id": "FTTVbaL4HBzjhzgstyLEhN3WrjEMDB8owqfLARNtJ2FX", + "owner": { + "id": "0xefe232372e2e30951fa90d7a800d5938eedc935d" + }, + "subgraphNumber": "4", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "EtGRQWQruHSy9sZUHwX4FKXQPT3p15xsV6Bx3Pt5LMHU", + "owner": { + "id": "0x03c65e533cc73cc65cd71a0cb65efa4b11e74c22" + }, + "subgraphNumber": "3", + "metadataHash": "0x3b9721ef654fc1de4fb3654d8b27eb152face455c64bab02011e417575cc1077" + }, + { + "id": "EsEnqMt8GrWXSWjdkTphcauCRvcyC1eC4U9sdBRZEB84", + "owner": { + "id": "0x5991a31ab4095cb5470a5bd532e02568393b06d5" + }, + "subgraphNumber": "1", + "metadataHash": "0x56899ebbe432ee9fe47db5fe709b0c47ef0e0fbe3cc5a7fde97861b0ff37cb41" + }, + { + "id": "E1vew3qN9voUJCmkPWUubQBBppiBuC2f3T2Exh2CsyDH", + "owner": { + "id": "0xefe232372e2e30951fa90d7a800d5938eedc935d" + }, + "subgraphNumber": "2", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "Dz55sRXXemD3QUos3orXQWm5GQs3ACECGDbE86ZVsyrG", + "owner": { + "id": "0x03c65e533cc73cc65cd71a0cb65efa4b11e74c22" + }, + "subgraphNumber": "4", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "DSpmdAKr3pzkcU5R6NgreBsYabdkY9C5ocBbP9Sk4FAA", + "owner": { + "id": "0x5ca1ea5549e4e7cb64ae35225e11865d2572b3f9" + }, + "subgraphNumber": "0", + "metadataHash": "0x7369f32b51f12127e0591f079c99f6b997d90aecbd938270c0d0ecf902edfb2a" + }, + { + "id": "CvkpgHJW4ApYwYX831M8GpN472FbnhGKjdL2ERT5wie9", + "owner": { + "id": "0x9d196973c0c5bd65ccfb797a2c23eb5c1faba7ab" + }, + "subgraphNumber": "1", + "metadataHash": "0x82a07620f76548e3d7b38b468b9b67b2e9355a3dcef48ac1a4ebf96eb588685e" + }, + { + "id": "BM3vXF5bRFy4NRYrYirEnkfNsi3veUetKrqvqxmwMPSP", + "owner": { + "id": "0x03c65e533cc73cc65cd71a0cb65efa4b11e74c22" + }, + "subgraphNumber": "0", + "metadataHash": "0xbd37407528628edbdc2703dd0297097e41bb95b101c382d6f8fddcd8f15df58a" + }, + { + "id": "B39LecV8UELFUxULRswPhcifsZWJ6qaLL29cGYMcCK4s", + "owner": { + "id": "0x534a9ac3d3401f80800375680bded6a84137d296" + }, + "subgraphNumber": "3", + "metadataHash": "0xeeee64a3f268f229331f0088d0ef92b65257eee2a50492ed763dd21254c00799" + }, + { + "id": "A4xtyhChUywTCww37fFBtjd1poY2kHtMNu2fwKuxSSB", + "owner": { + "id": "0xa508c16666c5b8981fa46eb32784fccc01942a71" + }, + "subgraphNumber": "2", + "metadataHash": "0x7a7ca98b60850593645a9348d47143c7f550e790e48e51c4820baddd92319d35" + }, + { + "id": "9xL1fnWqqQ4QjC9Z33hTXkgPBZAHU14Tzqzf5mEtDbxM", + "owner": { + "id": "0xefe232372e2e30951fa90d7a800d5938eedc935d" + }, + "subgraphNumber": "3", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "9js1z4GHLYQuGQ6yGs9SdcCRUDTCXBLKY7e37KFUKRre", + "owner": { + "id": "0x69aa76325b4890f0fa9b44f4d99d56f3834738b4" + }, + "subgraphNumber": "0", + "metadataHash": "0xcaf93a686e6b7f7d1b78543ffc512d4046b493b4d125dc3c6fc5469c4af57d70" + }, + { + "id": "9EjsLLp4Ti39xUfZE1Xzz6bjwuzJSc3tVb3FvYxugq65", + "owner": { + "id": "0x03c65e533cc73cc65cd71a0cb65efa4b11e74c22" + }, + "subgraphNumber": "2", + "metadataHash": "0x3b9721ef654fc1de4fb3654d8b27eb152face455c64bab02011e417575cc1077" + }, + { + "id": "8mteqsnKePqyqAXVb6e6KkcBqJpR3tjwPacgP1jSmxSE", + "owner": { + "id": "0x5991a31ab4095cb5470a5bd532e02568393b06d5" + }, + "subgraphNumber": "3", + "metadataHash": "0x7876a5e7860a6abe0acebdde502d39b180856c41163d536fa632725f1f58cd3b" + }, + { + "id": "7Y8ZaLST7xYVcVZsVRiRw2xhnDe9C62nLmLQpxffPVj", + "owner": { + "id": "0xefe232372e2e30951fa90d7a800d5938eedc935d" + }, + "subgraphNumber": "6", + "metadataHash": "0xbdfd81ed973596a181375b4e3c69d5a1fe52d2c41a07ec0ba5621a1e2bd35ddb" + }, + { + "id": "7fspzcqYDgVF1gV7VxyA2k833EmhYqnsgRvXk9YAEPT4", + "owner": { + "id": "0xa508c16666c5b8981fa46eb32784fccc01942a71" + }, + "subgraphNumber": "1", + "metadataHash": "0x7400f53d252f899ec54094484d9dc3102e38147755f7dbf9ddb3ad4e9487acb9" + }, + { + "id": "7Ew6SQmN1Xdjk5YEonqYAaT1v2HikNa92VZUQPpJ2QvX", + "owner": { + "id": "0x534a9ac3d3401f80800375680bded6a84137d296" + }, + "subgraphNumber": "5", + "metadataHash": "0x54bc59114d36eaec4ff6a196c6e40a33d4eca894c514f9b127238424a4188274" + }, + { + "id": "6SVLBaaAcujGWswitHpLixkgjQVZugrQHj8AihGJgFgD", + "owner": { + "id": "0xfcb576bc8ee187945fa00f0daa7bbe9c1b51b0c9" + }, + "subgraphNumber": "2", + "metadataHash": "0x7aba482a8b8b809d890f865548b5a2a194271ca9afcb0f5e47a604a286f4d9aa" + }, + { + "id": "6bsUMv2twT2SA9RCToCBDXfStADVvDh2nvEmSuX4F8kc", + "owner": { + "id": "0x0b1302c23d9eb4b42a74cbefc4f9b3081ff1bf18" + }, + "subgraphNumber": "0", + "metadataHash": "0xfa65e518e90b49586e173e29ae25202995c400ee021353d90c42b682c34494d6" + }, + { + "id": "6AmTt2V2PQiKJuHF6X1ySjJpNTuwzvUTmUQRYL74eFxT", + "owner": { + "id": "0xefe232372e2e30951fa90d7a800d5938eedc935d" + }, + "subgraphNumber": "5", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "5vhK8XAGXiK4zwGPcN2C63TjhAHtqyqoUcS6RGR5H86i", + "owner": { + "id": "0x673b6e9fe607f6ddf4a4f25b386b846c5c82995e" + }, + "subgraphNumber": "3", + "metadataHash": "0xddb85d0e63098b79b4340052b866c4d8eb638a81d74c6e135c979d23f4d1e93f" + }, + { + "id": "5qyjWvZ1FLwAsBeJvPuyvhBddJDavKYyyjdXQZ28REAJ", + "owner": { + "id": "0xf556322b497b475d535d0d4048f56c092a0ea3ad" + }, + "subgraphNumber": "1", + "metadataHash": "0x9bdee2ed59fcf9532df294d9b07fa1ef3c127a144658c35fa3c1d9fee4f7cc2a" + }, + { + "id": "57MzWCjGmKWrUYGHgEVne3ieFCXnwAUHKKDLXm4mJPJb", + "owner": { + "id": "0x03c65e533cc73cc65cd71a0cb65efa4b11e74c22" + }, + "subgraphNumber": "6", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "4MQwNPuso8ABKHhddwUmJCaPqg2w4Vst6B2pPr21Ygn9", + "owner": { + "id": "0xefe232372e2e30951fa90d7a800d5938eedc935d" + }, + "subgraphNumber": "1", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "47BEnfQFYjURYjD8r2JNoFjXkYHTqJ3xfcnrKUrbnTiq", + "owner": { + "id": "0x534a9ac3d3401f80800375680bded6a84137d296" + }, + "subgraphNumber": "2", + "metadataHash": "0xba7ebef4cc835813d6bdd70b2ee4db65594898e57e3412197964bd30b383e5fb" + }, + { + "id": "3zULJJdf5s9d87rn5aDgoT4pE5Uih3z6SAEumXy1dQqv", + "owner": { + "id": "0x03c65e533cc73cc65cd71a0cb65efa4b11e74c22" + }, + "subgraphNumber": "1", + "metadataHash": "0x45926246b7a13663ccacd05331419b7c2519bbc8b8bb6be89ab285022eb6e557" + }, + { + "id": "3sHuzLagq1T5yYrsctLtz7QdcNAGsdsodHk7j3g2mrVV", + "owner": { + "id": "0x03c65e533cc73cc65cd71a0cb65efa4b11e74c22" + }, + "subgraphNumber": "5", + "metadataHash": "0x5998fe5b6e689794aebf986beac1557367cba0f18d666bf8ec3aa037e6f08877" + }, + { + "id": "3caWu7riX9kGBe2zmXVc4V8vQQ5U1c3QAjzeSGNT7Jo", + "owner": { + "id": "0x072e829ff4e1c9bdb95acaf947f8ec262ecdf92f" + }, + "subgraphNumber": "0", + "metadataHash": "0x7f6fe58ac5f0c86007d61813897fcdb956f3f71e816f105b18f22cde4213ca20" + }, + { + "id": "2qbnVdk8RfatovF1sogHzH1eZ52DoziY6d7qR5KHzk8X", + "owner": { + "id": "0xc320812b4bbb7f2369ee1316fd703de403ad0d2e" + }, + "subgraphNumber": "0", + "metadataHash": "0xd9ff52d1ac82d8ebe295ee1bf3fd0f352eacb134039af2464342a7285cf0d921" + } + ] + } +} diff --git a/packages/contracts/scripts/ops/20240208-migrate-legacy-subgraphs/migrate.ts b/packages/contracts/scripts/ops/20240208-migrate-legacy-subgraphs/migrate.ts new file mode 100644 index 000000000..9e2cbdcba --- /dev/null +++ b/packages/contracts/scripts/ops/20240208-migrate-legacy-subgraphs/migrate.ts @@ -0,0 +1,63 @@ +import hre from 'hardhat' +import data from './data.json' +import { confirm, subgraphIdToHex } from '@graphprotocol/sdk' +import { BigNumber, ethers } from 'ethers' + +async function main() { + const graph = hre.graph() + const deployer = await graph.getDeployer() + + // First estimate cost + const gasEstimate = await data.data.subgraphs.reduce(async (acc, subgraph) => { + return (await acc).add( + await graph.contracts.L1GNS.connect(deployer).estimateGas.migrateLegacySubgraph( + subgraph.owner.id, + subgraph.subgraphNumber, + subgraph.metadataHash, + ), + ) + }, Promise.resolve(BigNumber.from(0))) + const gasPrice = await graph.provider.getGasPrice() + const cost = ethers.utils.formatEther(gasEstimate.mul(gasPrice)) + + // Ask for confirmation + if ( + !(await confirm( + `This script will migrate ${data.data.subgraphs.length} legacy subgraphs, with an approximate cost of ${cost} Ξ. Are you sure you want to continue?`, + false, + )) + ) + return + + // do it + for (const subgraph of data.data.subgraphs) { + console.log(`Migrating legacy subgraph ${subgraph.owner.id}/${subgraph.subgraphNumber}...`) + + const legacyKey = await graph.contracts.L1GNS.legacySubgraphKeys(subgraphIdToHex(subgraph.id)) + if (legacyKey.account !== ethers.constants.AddressZero) { + console.log(` - Already migrated, skipping`) + continue + } + try { + const tx = await graph.contracts.L1GNS.connect(deployer).migrateLegacySubgraph( + subgraph.owner.id, + subgraph.subgraphNumber, + subgraph.metadataHash, + ) + const receipt = await tx.wait() + if (receipt.status == 1) { + console.log(` ✔ Migration succeeded!`) + } else { + console.log(` ✖ Migration failed!`) + console.log(receipt) + } + } catch (error) { + console.log(error) + } + } +} + +main().catch((error) => { + console.error(error) + process.exitCode = 1 +}) diff --git a/packages/contracts/scripts/ops/parseTestnetAddresses.ts b/packages/contracts/scripts/ops/parseTestnetAddresses.ts index 96ad27be4..921859368 100755 --- a/packages/contracts/scripts/ops/parseTestnetAddresses.ts +++ b/packages/contracts/scripts/ops/parseTestnetAddresses.ts @@ -16,18 +16,18 @@ interface TeamMember { export const teamAddresses: Array = [] -async function main() { +function main() { const data = fs.readFileSync('indexers.csv', 'utf8') - const entries = data.split('\n').map((e) => e.trim()) + const entries = data.split('\n').map(e => e.trim()) for (const entry of entries) { if (!entry) continue - const [name, address] = entry.split(',').map((e) => e.trim()) + const [name, address] = entry.split(',').map(e => e.trim()) // Verify address try { getAddress(address.trim()) - } catch (err) { + } catch (_) { console.log('Invalid', name, address) process.exit(1) } diff --git a/packages/contracts/scripts/prepack b/packages/contracts/scripts/prepack new file mode 100755 index 000000000..bc0e54391 --- /dev/null +++ b/packages/contracts/scripts/prepack @@ -0,0 +1,20 @@ +#!/bin/bash + +TYPECHAIN_DIR=dist/types + +set -eo pipefail +set +o noglob + +# Build contracts +yarn clean +yarn build + +# Refresh distribution folder +rm -rf dist && mkdir -p ${TYPECHAIN_DIR} +cp -R build/abis/ dist/abis +cp -R build/types/ ${TYPECHAIN_DIR} + +# Build and create TS declarations +pushd ${TYPECHAIN_DIR} +ls *.ts **/*.ts | xargs tsc --esModuleInterop +popd diff --git a/packages/contracts/scripts/prepublish b/packages/contracts/scripts/prepublish deleted file mode 100755 index 60b4fcecd..000000000 --- a/packages/contracts/scripts/prepublish +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -TYPECHAIN_DIR=dist/types - -set -eo pipefail - -# Build contracts -yarn clean -yarn build - -# Refresh distribution folder -rm -rf dist && mkdir -p dist/types/_src -cp -R build/abis/ dist/abis -cp -R build/types/ dist/types/_src - -### Build Typechain bindings - -# Build and create TS declarations -tsc -d ${TYPECHAIN_DIR}/_src/*.ts --outdir ${TYPECHAIN_DIR} --esModuleInterop -# Copy back sources -cp ${TYPECHAIN_DIR}/_src/*.ts ${TYPECHAIN_DIR} -# Delete temporary src dir -rm -rf ${TYPECHAIN_DIR}/_src diff --git a/packages/contracts/scripts/test b/packages/contracts/scripts/test index d49b8535f..376090d90 100755 --- a/packages/contracts/scripts/test +++ b/packages/contracts/scripts/test @@ -35,6 +35,7 @@ mkdir -p reports DISABLE_SECURE_ACCOUNTS=true \ L1_GRAPH_CONFIG=config/graph.hardhat.yml \ L2_GRAPH_CONFIG=config/graph.arbitrum-hardhat.yml \ +ADDRESS_BOOK=addresses-local.json \ npx hardhat test --network hardhat $@ if [ "$REPORT_GAS" = true ]; then diff --git a/packages/contracts/scripts/upgrade b/packages/contracts/scripts/upgrade index 5b5708558..086f2d9b0 100755 --- a/packages/contracts/scripts/upgrade +++ b/packages/contracts/scripts/upgrade @@ -76,7 +76,7 @@ FORK=true npx hardhat e2e:upgrade "$UPGRADE_NAME" \ # Run upgrade print_separator "Upgrading contract" -FORK=true npx hardhat contracts:upgrade \ +FORK=true npx hardhat contract:upgrade \ --network localhost \ --graph-config "${GRAPH_CONFIG}" \ --address-book addresses-fork.json \ diff --git a/packages/contracts/tasks/bridge/configure.ts b/packages/contracts/tasks/bridge/configure.ts deleted file mode 100644 index 74c1a2e93..000000000 --- a/packages/contracts/tasks/bridge/configure.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { task } from 'hardhat/config' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' -import { - configureL1Bridge, - configureL2Bridge, - isGraphL1ChainId, - isGraphL2ChainId, -} from '@graphprotocol/sdk' - -export const TASK_BRIDGE_CONFIGURE_L1 = 'bridge:configure:l1' -export const TASK_BRIDGE_CONFIGURE_L2 = 'bridge:configure:l2' - -task(TASK_BRIDGE_CONFIGURE_L1, 'Configure L1 bridge') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam( - 'arbitrumAddressBook', - GRE_TASK_PARAMS.arbitrumAddressBook.description, - GRE_TASK_PARAMS.arbitrumAddressBook.default, - ) - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .setAction(async (taskArgs, hre) => { - const graph = hre.graph(taskArgs) - const { governor } = await graph.getNamedAccounts() - - if (isGraphL2ChainId(graph.chainId)) { - throw new Error('Cannot set L1 configuration on an L2 network!') - } - - await configureL1Bridge(graph.contracts, governor, { - l2GRTAddress: graph.l2.contracts.GraphToken.address, - l2GRTGatewayAddress: graph.l2.contracts.L2GraphTokenGateway.address, - l2GNSAddress: graph.l2.contracts.L2GNS.address, - l2StakingAddress: graph.l2.contracts.L2Staking.address, - arbAddressBookPath: taskArgs.arbitrumAddressBook, - chainId: graph.chainId, - }) - console.log('Done!') - }) - -task(TASK_BRIDGE_CONFIGURE_L2, 'Configure L2 bridge') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam( - 'arbitrumAddressBook', - GRE_TASK_PARAMS.arbitrumAddressBook.description, - GRE_TASK_PARAMS.arbitrumAddressBook.default, - ) - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .setAction(async (taskArgs, hre) => { - const graph = hre.graph(taskArgs) - const { governor } = await graph.getNamedAccounts() - - if (isGraphL1ChainId(graph.chainId)) { - throw new Error('Cannot set L2 configuration on an L1 network!') - } - - await configureL2Bridge(graph.contracts, governor, { - l1GRTAddress: graph.l1.contracts.GraphToken.address, - l1GRTGatewayAddress: graph.l1.contracts.L1GraphTokenGateway.address, - l1GNSAddress: graph.l1.contracts.L1GNS.address, - l1StakingAddress: graph.l1.contracts.L1Staking.address, - arbAddressBookPath: taskArgs.arbitrumAddressBook, - chainId: graph.chainId, - }) - console.log('Done!') - }) diff --git a/packages/contracts/tasks/bridge/deposits.ts b/packages/contracts/tasks/bridge/deposits.ts index e5c5f4660..b8a7838fc 100644 --- a/packages/contracts/tasks/bridge/deposits.ts +++ b/packages/contracts/tasks/bridge/deposits.ts @@ -1,20 +1,17 @@ -import { task } from 'hardhat/config' +import { greTask } from '@graphprotocol/sdk/gre' import { ethers } from 'ethers' import { Table } from 'console-table-printer' import { L1ToL2MessageStatus } from '@arbitrum/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' import { getL1ToL2MessageStatus } from '@graphprotocol/sdk' -export const TASK_BRIDGE_DEPOSITS = 'bridge:deposits' -task(TASK_BRIDGE_DEPOSITS, 'List deposits initiated on L1GraphTokenGateway') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam( - 'arbitrumAddressBook', - GRE_TASK_PARAMS.arbitrumAddressBook.description, - GRE_TASK_PARAMS.arbitrumAddressBook.default, - ) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) +interface PrintEvent { + blockNumber: string + tx: string + amount: string + status: string +} + +greTask('bridge:deposits', 'List deposits initiated on L1GraphTokenGateway') .addOptionalParam('startBlock', 'Start block for the search') .addOptionalParam('endBlock', 'End block for the search') .setAction(async (taskArgs, hre) => { @@ -31,7 +28,7 @@ task(TASK_BRIDGE_DEPOSITS, 'List deposits initiated on L1GraphTokenGateway') const events = await Promise.all( ( await gateway.queryFilter(gateway.filters.DepositInitiated(), startBlock, endBlock) - ).map(async (e) => ({ + ).map(async e => ({ blockNumber: `${e.blockNumber} (${new Date( (await graph.l1.provider.getBlock(e.blockNumber)).timestamp * 1000, ).toLocaleString()})`, @@ -58,7 +55,7 @@ task(TASK_BRIDGE_DEPOSITS, 'List deposits initiated on L1GraphTokenGateway') printEvents(events) }) -function printEvents(events: any[]) { +function printEvents(events: PrintEvent[]) { const tablePrinter = new Table({ charLength: { '🚧': 2, '✅': 2, '⚠️': 1, '⌛': 2, '❌': 2 }, columns: [ @@ -74,7 +71,7 @@ function printEvents(events: any[]) { ], }) - events.map((e) => tablePrinter.addRow(e)) + events.map(e => tablePrinter.addRow(e)) tablePrinter.printTable() } diff --git a/packages/contracts/tasks/bridge/to-l2.ts b/packages/contracts/tasks/bridge/to-l2.ts index 7b1548d1f..8f05aac87 100644 --- a/packages/contracts/tasks/bridge/to-l2.ts +++ b/packages/contracts/tasks/bridge/to-l2.ts @@ -1,24 +1,15 @@ -import { task } from 'hardhat/config' import { BigNumber } from 'ethers' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' +import { greTask } from '@graphprotocol/sdk/gre' import { sendToL2 } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { TASK_NITRO_SETUP_SDK } from '../deployment/nitro' -export const TASK_BRIDGE_TO_L2 = 'bridge:send-to-l2' - -task(TASK_BRIDGE_TO_L2, 'Bridge GRT tokens from L1 to L2') +greTask('bridge:send-to-l2', 'Bridge GRT tokens from L1 to L2') .addParam('amount', 'Amount of tokens to bridge') - .addOptionalParam('sender', 'Address of the sender. L1 deployer if empty.') - .addOptionalParam('recipient', 'Receiving address in L2. Same to L1 address if empty.') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) .addOptionalParam( - 'arbitrumAddressBook', - GRE_TASK_PARAMS.arbitrumAddressBook.description, - GRE_TASK_PARAMS.arbitrumAddressBook.default, + 'sender', + 'Address of the sender, must be managed by the provider node. L1 deployer if empty.', ) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) + .addOptionalParam('recipient', 'Receiving address in L2. Same to L1 address if empty.') .addOptionalParam( 'deploymentFile', 'Nitro testnode deployment file. Must specify if using nitro test nodes.', @@ -30,18 +21,14 @@ task(TASK_BRIDGE_TO_L2, 'Bridge GRT tokens from L1 to L2') // If local, add nitro test node networks to sdk if (taskArgs.deploymentFile) { console.log('> Adding nitro test node network to sdk') - await hre.run(TASK_NITRO_SETUP_SDK, { deploymentFile: taskArgs.deploymentFile }) + await hre.run('migrate:nitro:register', { deploymentFile: taskArgs.deploymentFile }) } // Get the sender, use L1 deployer if not provided - const l1Deployer = await graph.l1.getDeployer() - const sender: string = taskArgs.sender ?? l1Deployer.address - - const signer = await SignerWithAddress.create(graph.l1.provider.getSigner(sender)) - if (!signer) { - throw new Error(`No wallet found for address ${sender}`) - } - console.log(`> Using wallet ${signer.address}`) + const sender = taskArgs.sender + ? await SignerWithAddress.create(graph.l1.provider.getSigner(taskArgs.sender)) + : await graph.l1.getDeployer() + console.log(`> Using wallet ${sender.address}`) // Patch sendToL2 opts taskArgs.l2Provider = graph.l2.provider @@ -52,7 +39,7 @@ task(TASK_BRIDGE_TO_L2, 'Bridge GRT tokens from L1 to L2') taskArgs.maxGas = BigNumber.from('400000') } - await sendToL2(graph.contracts, signer, { + await sendToL2(graph.contracts, sender, { l2Provider: graph.l2.provider, amount: taskArgs.amount, recipient: taskArgs.recipient, diff --git a/packages/contracts/tasks/bridge/withdrawals.ts b/packages/contracts/tasks/bridge/withdrawals.ts index fba0c67ab..d36511813 100644 --- a/packages/contracts/tasks/bridge/withdrawals.ts +++ b/packages/contracts/tasks/bridge/withdrawals.ts @@ -1,21 +1,17 @@ -import { task } from 'hardhat/config' import { ethers } from 'ethers' import { Table } from 'console-table-printer' import { L2ToL1MessageStatus } from '@arbitrum/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' +import { greTask } from '@graphprotocol/sdk/gre' import { getL2ToL1MessageStatus } from '@graphprotocol/sdk' -export const TASK_BRIDGE_WITHDRAWALS = 'bridge:withdrawals' +interface PrintEvent { + blockNumber: string + tx: string + amount: string + status: string +} -task(TASK_BRIDGE_WITHDRAWALS, 'List withdrawals initiated on L2GraphTokenGateway') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam( - 'arbitrumAddressBook', - GRE_TASK_PARAMS.arbitrumAddressBook.description, - GRE_TASK_PARAMS.arbitrumAddressBook.default, - ) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) +greTask('bridge:withdrawals', 'List withdrawals initiated on L2GraphTokenGateway') .addOptionalParam('startBlock', 'Start block for the search') .addOptionalParam('endBlock', 'End block for the search') .setAction(async (taskArgs, hre) => { @@ -32,7 +28,7 @@ task(TASK_BRIDGE_WITHDRAWALS, 'List withdrawals initiated on L2GraphTokenGateway const events = await Promise.all( ( await gateway.queryFilter(gateway.filters.WithdrawalInitiated(), startBlock, endBlock) - ).map(async (e) => ({ + ).map(async e => ({ blockNumber: `${e.blockNumber} (${new Date( (await graph.l2.provider.getBlock(e.blockNumber)).timestamp * 1000, ).toLocaleString()})`, @@ -59,7 +55,7 @@ task(TASK_BRIDGE_WITHDRAWALS, 'List withdrawals initiated on L2GraphTokenGateway printEvents(events) }) -function printEvents(events: any[]) { +function printEvents(events: PrintEvent[]) { const tablePrinter = new Table({ charLength: { '🚧': 2, '✅': 2, '⚠️': 1, '❌': 2 }, columns: [ @@ -75,7 +71,7 @@ function printEvents(events: any[]) { ], }) - events.map((e) => tablePrinter.addRow(e)) + events.map(e => tablePrinter.addRow(e)) tablePrinter.printTable() } diff --git a/packages/contracts/tasks/contract/deploy.ts b/packages/contracts/tasks/contract/deploy.ts new file mode 100644 index 000000000..3571444d0 --- /dev/null +++ b/packages/contracts/tasks/contract/deploy.ts @@ -0,0 +1,43 @@ +import { confirm, deploy, DeployType, GraphNetworkAddressBook } from '@graphprotocol/sdk' +import { greTask } from '@graphprotocol/sdk/gre' + +greTask('contract:deploy', 'Deploy a contract') + .addPositionalParam('contract', 'Name of the contract to deploy') + .addOptionalPositionalParam( + 'init', + 'Initialization arguments for the contract constructor. Provide arguments as comma-separated values', + ) + .addParam('deployType', 'Choose deploy, deploy-save, deploy-with-proxy, deploy-with-proxy-save') + .addFlag('skipConfirmation', 'Skip confirmation prompt on write actions') + .addFlag('buildAcceptTx', '...') + .setAction(async (taskArgs, hre) => { + const graph = hre.graph(taskArgs) + const deployer = await graph.getDeployer() + + if (!Object.values(DeployType).includes(taskArgs.deployType)) { + throw new Error(`Deploy type ${taskArgs.deployType} not supported`) + } + + console.log(`Deploying ${taskArgs.contract}...`) + console.log(`Init: ${taskArgs.init}`) + console.log(`Deploy type: ${taskArgs.deployType}`) + console.log(`Deployer: ${deployer.address}`) + console.log(`Chain ID: ${graph.chainId}`) + + const sure = await confirm( + `Are you sure to deploy ${taskArgs.contract}?`, + taskArgs.skipConfirmation, + ) + if (!sure) return + + const deployment = await deploy( + taskArgs.deployType, + deployer, + { + name: taskArgs.contract, + args: taskArgs.init?.split(',') || [], + }, + new GraphNetworkAddressBook(taskArgs.addressBook, graph.chainId), + ) + console.log(`Contract deployed at ${deployment.contract.address}`) + }) diff --git a/packages/contracts/tasks/contracts/upgrade.ts b/packages/contracts/tasks/contract/upgrade.ts similarity index 71% rename from packages/contracts/tasks/contracts/upgrade.ts rename to packages/contracts/tasks/contract/upgrade.ts index 586335736..6825ba06a 100644 --- a/packages/contracts/tasks/contracts/upgrade.ts +++ b/packages/contracts/tasks/contract/upgrade.ts @@ -1,20 +1,8 @@ -import { task } from 'hardhat/config' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' -import { DeployType, GraphNetworkAddressBook, deploy } from '@graphprotocol/sdk' +import { greTask } from '@graphprotocol/sdk/gre' +import { deploy, DeployType, GraphNetworkAddressBook } from '@graphprotocol/sdk' -task('contracts:upgrade', 'Upgrades a contract') +greTask('contract:upgrade', 'Upgrades a contract') .addParam('contract', 'Name of the contract to upgrade') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addOptionalParam( - 'graphConfig', - GRE_TASK_PARAMS.graphConfig.description, - GRE_TASK_PARAMS.graphConfig.default, - ) - .addOptionalParam( - 'addressBook', - GRE_TASK_PARAMS.addressBook.description, - GRE_TASK_PARAMS.addressBook.default, - ) .addOptionalVariadicPositionalParam( 'init', 'Initialization arguments for the contract constructor', diff --git a/packages/contracts/tasks/deployment/accounts.ts b/packages/contracts/tasks/deployment/accounts.ts deleted file mode 100644 index 8f0d81cb3..000000000 --- a/packages/contracts/tasks/deployment/accounts.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { writeConfig, updateItemValue } from '@graphprotocol/sdk' -import { task } from 'hardhat/config' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' - -task('migrate:accounts', 'Creates protocol accounts and saves them in graph config') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .setAction(async (taskArgs, hre) => { - const { graphConfig, getDeployer } = hre.graph(taskArgs) - - console.log('> Generating addresses') - - const deployer = await getDeployer() - const [ - , - arbitrator, - governor, - authority, - availabilityOracle, - pauseGuardian, - allocationExchangeOwner, - ] = await hre.ethers.getSigners() - - console.log(`- Deployer: ${deployer.address}`) - console.log(`- Arbitrator: ${arbitrator.address}`) - console.log(`- Governor: ${governor.address}`) - console.log(`- Authority: ${authority.address}`) - console.log(`- Availability Oracle: ${availabilityOracle.address}`) - console.log(`- Pause Guardian: ${pauseGuardian.address}`) - console.log(`- Allocation Exchange Owner: ${allocationExchangeOwner.address}`) - - updateItemValue(graphConfig, 'general/arbitrator', arbitrator.address) - updateItemValue(graphConfig, 'general/governor', governor.address) - updateItemValue(graphConfig, 'general/authority', authority.address) - updateItemValue(graphConfig, 'general/availabilityOracle', availabilityOracle.address) - updateItemValue(graphConfig, 'general/pauseGuardian', pauseGuardian.address) - updateItemValue(graphConfig, 'general/allocationExchangeOwner', allocationExchangeOwner.address) - - writeConfig(taskArgs.graphConfig, graphConfig.toString()) - }) diff --git a/packages/contracts/tasks/deployment/config.ts b/packages/contracts/tasks/deployment/config.ts index 0121cf4b6..76192b1c3 100644 --- a/packages/contracts/tasks/deployment/config.ts +++ b/packages/contracts/tasks/deployment/config.ts @@ -1,23 +1,16 @@ -import { task } from 'hardhat/config' - import { + confirm, GraphNetworkConfigContractList, GraphNetworkConfigGeneralParams, updateContractParams, updateGeneralParams, writeConfig, - confirm, } from '@graphprotocol/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' +import { greTask } from '@graphprotocol/sdk/gre' -task('update-config', 'Update graph config parameters with onchain data') - .addParam( - 'graphConfig', - GRE_TASK_PARAMS.graphConfig.description, - GRE_TASK_PARAMS.graphConfig.default, - ) - .addFlag('dryRun', "Only print the changes, don't write them to the config file") - .addFlag('skipConfirmation', GRE_TASK_PARAMS.skipConfirmation.description) +greTask('update-config', 'Update graph config parameters with onchain data') + .addFlag('dryRun', 'Only print the changes, don\'t write them to the config file') + .addFlag('skipConfirmation', 'Skip confirmation prompt on write actions.') .setAction(async (taskArgs, hre) => { const networkName = hre.network.name const configFile = taskArgs.graphConfig diff --git a/packages/contracts/tasks/deployment/deploy.ts b/packages/contracts/tasks/deployment/deploy.ts deleted file mode 100644 index 2e33a3b87..000000000 --- a/packages/contracts/tasks/deployment/deploy.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { task } from 'hardhat/config' - -import { - GraphChainId, - deployGraphNetwork, - helpers, - isGraphChainL1Localhost, -} from '@graphprotocol/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' - -task('migrate', 'Migrate contracts') - .addParam( - 'addressBook', - GRE_TASK_PARAMS.addressBook.description, - GRE_TASK_PARAMS.addressBook.default, - ) - .addParam( - 'graphConfig', - GRE_TASK_PARAMS.graphConfig.description, - GRE_TASK_PARAMS.graphConfig.default, - ) - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addFlag('skipConfirmation', GRE_TASK_PARAMS.skipConfirmation.description) - .addFlag('force', GRE_TASK_PARAMS.force.description) - .addFlag('buildAcceptTx', '...') - .setAction(async (taskArgs, hre) => { - const graph = hre.graph(taskArgs) - - await deployGraphNetwork( - taskArgs.addressBook, - taskArgs.graphConfig, - graph.chainId as GraphChainId, // TODO: fix type - await graph.getDeployer(), - graph.provider, - { - forceDeploy: taskArgs.force, - skipConfirmation: taskArgs.skipConfirmation, - buildAcceptTx: taskArgs.buildAcceptTx, - }, - ) - }) diff --git a/packages/contracts/tasks/deployment/nitro.ts b/packages/contracts/tasks/deployment/nitro.ts deleted file mode 100644 index b5819f26a..000000000 --- a/packages/contracts/tasks/deployment/nitro.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { BigNumber, ContractTransaction } from 'ethers' -import { subtask, task } from 'hardhat/config' -import { addCustomNetwork } from '@arbitrum/sdk/dist/lib/dataEntities/networks' -import fs from 'fs' -import { execSync } from 'child_process' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' -import { helpers } from '@graphprotocol/sdk' - -export const TASK_NITRO_FUND_ACCOUNTS = 'nitro:fund-accounts' -export const TASK_NITRO_SETUP_SDK = 'nitro:sdk-setup' -export const TASK_NITRO_SETUP_ADDRESS_BOOK = 'nitro:address-book-setup' -export const TASK_NITRO_FETCH_DEPLOYMENT_FILE = 'nitro:fetch-deployment-file' - -task(TASK_NITRO_FUND_ACCOUNTS, 'Funds protocol accounts on Arbitrum Nitro testnodes') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('privateKey', 'The private key for Arbitrum testnode genesis account') - .addOptionalParam('amount', 'The amount to fund each account with') - .setAction(async (taskArgs, hre) => { - // Arbitrum Nitro testnodes have a pre-funded genesis account whose private key is hardcoded here: - // - L1 > https://github.com/OffchainLabs/nitro/blob/01c558c06ad9cbaa083bebe3e51960e195c3fd6b/test-node.bash#L136 - // - L2 > https://github.com/OffchainLabs/nitro/blob/01c558c06ad9cbaa083bebe3e51960e195c3fd6b/testnode-scripts/config.ts#L22 - const genesisAccountPrivateKey = - taskArgs.privateKey ?? 'b6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659' - const genesisAccount = new hre.ethers.Wallet(genesisAccountPrivateKey) - - // Get protocol accounts - const { getDeployer, getNamedAccounts, getTestAccounts, provider } = hre.graph(taskArgs) - const deployer = await getDeployer() - const testAccounts = await getTestAccounts() - const namedAccounts = await getNamedAccounts() - const accounts = [ - deployer, - ...testAccounts, - ...Object.keys(namedAccounts).map((k) => namedAccounts[k]), - ] - - // Amount to fund - // - If amount is specified, use that - // - Otherwise, use 95% of genesis account balance with a maximum of 100 Eth - let amount: BigNumber - const maxAmount = hre.ethers.utils.parseEther('100') - const genesisAccountBalance = await provider.getBalance(genesisAccount.address) - - if (taskArgs.amount) { - amount = hre.ethers.BigNumber.from(taskArgs.amount) - } else { - const splitGenesisBalance = genesisAccountBalance.mul(95).div(100).div(accounts.length) - if (splitGenesisBalance.gt(maxAmount)) { - amount = maxAmount - } else { - amount = splitGenesisBalance - } - } - - // Check genesis account balance - const requiredFunds = amount.mul(accounts.length) - if (genesisAccountBalance.lt(requiredFunds)) { - throw new Error('Insufficient funds in genesis account') - } - - // Fund accounts - console.log('> Funding protocol addresses') - console.log(`Genesis account: ${genesisAccount.address}`) - console.log(`Total accounts: ${accounts.length}`) - console.log(`Amount per account: ${hre.ethers.utils.formatEther(amount)}`) - console.log(`Required funds: ${hre.ethers.utils.formatEther(requiredFunds)}`) - - const txs: ContractTransaction[] = [] - for (const account of accounts) { - const tx = await genesisAccount.connect(provider).sendTransaction({ - value: amount, - to: account.address, - }) - txs.push(tx) - } - await Promise.all(txs.map((tx) => tx.wait())) - console.log('Done!') - }) - -// Arbitrum SDK does not support Nitro testnodes out of the box -// This adds the testnodes to the SDK configuration -subtask(TASK_NITRO_SETUP_SDK, 'Adds nitro testnodes to SDK config') - .addParam('deploymentFile', 'The testnode deployment file to use', 'localNetwork.json') - .setAction(async (taskArgs) => { - helpers.addLocalNetwork(taskArgs.deploymentFile) - }) - -subtask(TASK_NITRO_FETCH_DEPLOYMENT_FILE, 'Fetches nitro deployment file from a local testnode') - .addParam( - 'deploymentFile', - 'Path to the file where to deployment file will be saved', - 'localNetwork.json', - ) - .setAction(async (taskArgs) => { - console.log(`Attempting to fetch deployment file from testnode...`) - - const command = `docker container cp $(docker ps -alqf "name=tokenbridge" --format "{{.ID}}"):/workspace/localNetwork.json .` - const stdOut = execSync(command) - console.log(stdOut.toString()) - - if (!fs.existsSync(taskArgs.deploymentFile)) { - throw new Error(`Unable to fetch deployment file: ${taskArgs.deploymentFile}`) - } - console.log(`Deployment file saved to ${taskArgs.deploymentFile}`) - }) - -// Read arbitrum contract addresses from deployment file and write them to the address book -task(TASK_NITRO_SETUP_ADDRESS_BOOK, 'Write arbitrum addresses to address book') - .addParam('deploymentFile', 'The testnode deployment file to use') - .addParam('arbitrumAddressBook', 'Arbitrum address book file') - .setAction(async (taskArgs, hre) => { - if (!fs.existsSync(taskArgs.deploymentFile)) { - await hre.run(TASK_NITRO_FETCH_DEPLOYMENT_FILE, taskArgs) - } - const deployment = JSON.parse(fs.readFileSync(taskArgs.deploymentFile, 'utf-8')) - - const addressBook = { - '1337': { - L1GatewayRouter: { - address: deployment.l2Network.tokenBridge.l1GatewayRouter, - }, - IInbox: { - address: deployment.l2Network.ethBridge.inbox, - }, - }, - '412346': { - L2GatewayRouter: { - address: deployment.l2Network.tokenBridge.l2GatewayRouter, - }, - }, - } - - fs.writeFileSync(taskArgs.arbitrumAddressBook, JSON.stringify(addressBook)) - }) diff --git a/packages/contracts/tasks/deployment/ownership.ts b/packages/contracts/tasks/deployment/ownership.ts deleted file mode 100644 index 77004dd11..000000000 --- a/packages/contracts/tasks/deployment/ownership.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { ContractTransaction } from 'ethers' -import { task } from 'hardhat/config' -import { GraphNetworkContractName, acceptOwnership } from '@graphprotocol/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' - -task('migrate:ownership', 'Accepts ownership of protocol contracts on behalf of governor') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .setAction(async (taskArgs, hre) => { - const graph = hre.graph(taskArgs) - const { governor } = await graph.getNamedAccounts() - - console.log('> Accepting ownership of contracts') - console.log(`- Governor: ${governor.address}`) - - const governedContracts: GraphNetworkContractName[] = [ - 'GraphToken', - 'Controller', - 'GraphProxyAdmin', - 'SubgraphNFT', - ] - const txs: ContractTransaction[] = [] - for (const contract of governedContracts) { - const tx = await acceptOwnership(graph.contracts, governor, { contractName: contract }) - if (tx) { - txs.push() - } - } - - await Promise.all(txs.map((tx) => tx.wait())) - console.log('Done!') - }) diff --git a/packages/contracts/tasks/deployment/sync.ts b/packages/contracts/tasks/deployment/sync.ts deleted file mode 100644 index a0acf2da3..000000000 --- a/packages/contracts/tasks/deployment/sync.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { isGraphL2ChainId } from '@graphprotocol/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' -import { ContractTransaction } from 'ethers' -import { task } from 'hardhat/config' - -task('migrate:sync', 'Sync controller contracts') - .addParam( - 'addressBook', - GRE_TASK_PARAMS.addressBook.description, - GRE_TASK_PARAMS.addressBook.default, - ) - .addParam( - 'graphConfig', - GRE_TASK_PARAMS.graphConfig.description, - GRE_TASK_PARAMS.graphConfig.default, - ) - .setAction(async (taskArgs, hre) => { - const { contracts, getDeployer } = hre.graph({ - addressBook: taskArgs.addressBook, - graphConfig: taskArgs.graphConfig, - }) - const deployer = await getDeployer() - - const chainId = hre.network.config.chainId?.toString() ?? '1337' - const isL2 = isGraphL2ChainId(chainId) - - // Sync contracts - console.log( - `Syncing cache for contract addresses on chainId ${chainId} (${isL2 ? 'L2' : 'L1'})`, - ) - const txs: ContractTransaction[] = [] - console.log('> Syncing cache on Curation') - txs.push(await contracts['Curation'].connect(deployer).syncAllContracts()) - console.log('> Syncing cache on GNS') - txs.push(await contracts['GNS'].connect(deployer).syncAllContracts()) - console.log('> Syncing cache on ServiceRegistry') - txs.push(await contracts['ServiceRegistry'].connect(deployer).syncAllContracts()) - console.log('> Syncing cache on DisputeManager') - txs.push(await contracts['DisputeManager'].connect(deployer).syncAllContracts()) - console.log('> Syncing cache on RewardsManager') - txs.push(await contracts['RewardsManager'].connect(deployer).syncAllContracts()) - console.log('> Syncing cache on Staking') - txs.push(await contracts['Staking'].connect(deployer).syncAllContracts()) - if (isL2) { - console.log('> Syncing cache on L2GraphTokenGateway') - txs.push(await contracts['L2GraphTokenGateway'].connect(deployer).syncAllContracts()) - if (contracts['L2Reservoir']) { - console.log('> Syncing cache on L2Reservoir') - txs.push(await contracts['L2Reservoir'].connect(deployer).syncAllContracts()) - } - } else { - // L1 chains might not have these contracts deployed yet... - if (contracts['L1GraphTokenGateway']) { - console.log('> Syncing cache on L1GraphTokenGateway') - txs.push(await contracts['L1GraphTokenGateway'].connect(deployer).syncAllContracts()) - } else { - console.log('Skipping L1GraphTokenGateway as it does not seem to be deployed yet') - } - if (contracts['BridgeEscrow']) { - console.log('> Syncing cache on BridgeEscrow') - txs.push(await contracts['BridgeEscrow'].connect(deployer).syncAllContracts()) - } else { - console.log('Skipping BridgeEscrow as it does not seem to be deployed yet') - } - if (contracts['L1Reservoir']) { - console.log('> Syncing cache on L1Reservoir') - txs.push(await contracts['L1Reservoir'].connect(deployer).syncAllContracts()) - } else { - console.log('Skipping L1Reservoir as it does not seem to be deployed yet') - } - } - await Promise.all( - txs.map((tx) => { - console.log(tx.hash) - return tx.wait() - }), - ) - console.log('Done!') - }) diff --git a/packages/contracts/tasks/deployment/unpause.ts b/packages/contracts/tasks/deployment/unpause.ts deleted file mode 100644 index 12a649a3f..000000000 --- a/packages/contracts/tasks/deployment/unpause.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { task } from 'hardhat/config' -import { isGraphL2ChainId } from '@graphprotocol/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' - -task('migrate:unpause:protocol', 'Unpause protocol (except bridge)') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .setAction(async (taskArgs, hre) => { - const graph = hre.graph(taskArgs) - const { governor } = await graph.getNamedAccounts() - const { Controller } = graph.contracts - - console.log('> Unpausing protocol') - const tx = await Controller.connect(governor).setPaused(false) - await tx.wait() - - console.log('Done!') - }) - -task('migrate:unpause:bridge', 'Unpause bridge') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .setAction(async (taskArgs, hre) => { - const graph = hre.graph(taskArgs) - const { governor } = await graph.getNamedAccounts() - const { L1GraphTokenGateway, L2GraphTokenGateway } = graph.contracts - - console.log('> Unpausing bridge') - const GraphTokenGateway = isGraphL2ChainId(graph.chainId) - ? L2GraphTokenGateway - : L1GraphTokenGateway - const tx = await GraphTokenGateway.connect(governor).setPaused(false) - await tx.wait() - - console.log('Done!') - }) diff --git a/packages/contracts/tasks/e2e/e2e.ts b/packages/contracts/tasks/e2e/e2e.ts index 61946342e..43f23ad1e 100644 --- a/packages/contracts/tasks/e2e/e2e.ts +++ b/packages/contracts/tasks/e2e/e2e.ts @@ -1,18 +1,17 @@ -import { task } from 'hardhat/config' import { HardhatRuntimeEnvironment, TaskArguments } from 'hardhat/types' import { TASK_TEST } from 'hardhat/builtin-tasks/task-names' import glob from 'glob' import fs from 'fs' import { runScriptWithHardhat } from 'hardhat/internal/util/scripts-runner' import { isGraphL1ChainId } from '@graphprotocol/sdk' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' +import { greTask } from '@graphprotocol/sdk/gre' -const CONFIG_TESTS = 'e2e/deployment/config/**/*.test.ts' -const INIT_TESTS = 'e2e/deployment/init/**/*.test.ts' +const CONFIG_TESTS = 'test/e2e/deployment/config/**/*.test.ts' +const INIT_TESTS = 'test/e2e/deployment/init/**/*.test.ts' // Built-in test & run tasks don't support GRE arguments // so we pass them by overriding GRE config object -const setGraphConfig = async (args: TaskArguments, hre: HardhatRuntimeEnvironment) => { +const setGraphConfig = (args: TaskArguments, hre: HardhatRuntimeEnvironment) => { const greArgs = [ 'graphConfig', 'l1GraphConfig', @@ -34,11 +33,7 @@ const setGraphConfig = async (args: TaskArguments, hre: HardhatRuntimeEnvironmen } } -task('e2e', 'Run all e2e tests') - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) +greTask('e2e', 'Run all e2e tests') .addFlag('skipBridge', 'Skip bridge tests') .setAction(async (args, hre: HardhatRuntimeEnvironment) => { let testFiles = [ @@ -47,7 +42,7 @@ task('e2e', 'Run all e2e tests') ] if (args.skipBridge) { - testFiles = testFiles.filter((file) => !['l1', 'l2'].includes(file.split('/')[3])) + testFiles = testFiles.filter(file => !/l1|l2/.test(file)) } // Disable secure accounts, we don't need them for this task @@ -59,12 +54,8 @@ task('e2e', 'Run all e2e tests') }) }) -task('e2e:config', 'Run deployment configuration e2e tests') - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .setAction(async (args, hre: HardhatRuntimeEnvironment) => { +greTask('e2e:config', 'Run deployment configuration e2e tests').setAction( + async (args, hre: HardhatRuntimeEnvironment) => { const files = new glob.GlobSync(CONFIG_TESTS).found // Disable secure accounts, we don't need them for this task @@ -74,14 +65,11 @@ task('e2e:config', 'Run deployment configuration e2e tests') await hre.run(TASK_TEST, { testFiles: files, }) - }) + }, +) -task('e2e:init', 'Run deployment initialization e2e tests') - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .setAction(async (args, hre: HardhatRuntimeEnvironment) => { +greTask('e2e:init', 'Run deployment initialization e2e tests').setAction( + async (args, hre: HardhatRuntimeEnvironment) => { const files = new glob.GlobSync(INIT_TESTS).found // Disable secure accounts, we don't need them for this task @@ -91,21 +79,17 @@ task('e2e:init', 'Run deployment initialization e2e tests') await hre.run(TASK_TEST, { testFiles: files, }) - }) + }, +) -task('e2e:scenario', 'Run scenario scripts and e2e tests') +greTask('e2e:scenario', 'Run scenario scripts and e2e tests') .addPositionalParam('scenario', 'Name of the scenario to run') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addFlag('skipScript', "Don't run scenario script") + .addFlag('skipScript', 'Don\'t run scenario script') .setAction(async (args, hre: HardhatRuntimeEnvironment) => { setGraphConfig(args, hre) - const script = `e2e/scenarios/${args.scenario}.ts` - const test = `e2e/scenarios/${args.scenario}.test.ts` + const script = `test/e2e/scenarios/${args.scenario}.ts` + const test = `test/e2e/scenarios/${args.scenario}.test.ts` console.log(`> Running scenario: ${args.scenario}`) console.log(`- script file: ${script}`) @@ -134,23 +118,18 @@ task('e2e:scenario', 'Run scenario scripts and e2e tests') } }) -task('e2e:upgrade', 'Run upgrade tests') +greTask('e2e:upgrade', 'Run upgrade tests') .addPositionalParam('upgrade', 'Name of the upgrade to run') - .addFlag('disableSecureAccounts', 'Disable secure accounts on GRE') - .addFlag('fork', 'Enable fork behavior on GRE') .addFlag('post', 'Wether to run pre/post upgrade scripts') - .addOptionalParam('addressBook', GRE_TASK_PARAMS.addressBook.description) - .addOptionalParam('graphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l1GraphConfig', GRE_TASK_PARAMS.graphConfig.description) - .addOptionalParam('l2GraphConfig', GRE_TASK_PARAMS.graphConfig.description) .setAction(async (args, hre: HardhatRuntimeEnvironment) => { setGraphConfig(args, hre) await runUpgrade(args, hre, args.post ? 'post' : 'pre') }) -async function runUpgrade(args: any, hre: HardhatRuntimeEnvironment, type: 'pre' | 'post') { - const script = `e2e/upgrades/${args.upgrade}/${type}-upgrade.ts` - const test = `e2e/upgrades/${args.upgrade}/${type}-upgrade.test.ts` +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function runUpgrade(args: { [key: string]: any }, hre: HardhatRuntimeEnvironment, type: 'pre' | 'post') { + const script = `test/e2e/upgrades/${args.upgrade}/${type}-upgrade.ts` + const test = `test/e2e/upgrades/${args.upgrade}/${type}-upgrade.test.ts` console.log(`> Running ${type}-upgrade: ${args.upgrade}`) console.log(`- script file: ${script}`) diff --git a/packages/contracts/tasks/migrate/bridge.ts b/packages/contracts/tasks/migrate/bridge.ts new file mode 100644 index 000000000..85f710d2a --- /dev/null +++ b/packages/contracts/tasks/migrate/bridge.ts @@ -0,0 +1,37 @@ +import { greTask } from '@graphprotocol/sdk/gre' +import { configureL1Bridge, configureL2Bridge, setPausedBridge } from '@graphprotocol/sdk' + +greTask('migrate:bridge', 'Configure and unpause bridge') + .addOptionalParam( + 'arbitrumAddressBook', + 'The path to the address book file for Arbitrum deployments', + './arbitrum-addresses.json', + ) + .setAction(async (taskArgs, hre) => { + const graph = hre.graph(taskArgs) + const { governor: l1Governor } = await graph.l1.getNamedAccounts() + const { governor: l2Governor } = await graph.l2.getNamedAccounts() + + await configureL1Bridge(graph.l1.contracts, l1Governor, { + l2GRTAddress: graph.l2.contracts.GraphToken.address, + l2GRTGatewayAddress: graph.l2.contracts.L2GraphTokenGateway.address, + l2GNSAddress: graph.l2.contracts.L2GNS.address, + l2StakingAddress: graph.l2.contracts.L2Staking.address, + arbAddressBookPath: taskArgs.arbitrumAddressBook, + chainId: graph.l1.chainId, + }) + + await configureL2Bridge(graph.l2.contracts, l2Governor, { + l1GRTAddress: graph.l1.contracts.GraphToken.address, + l1GRTGatewayAddress: graph.l1.contracts.L1GraphTokenGateway.address, + l1GNSAddress: graph.l1.contracts.L1GNS.address, + l1StakingAddress: graph.l1.contracts.L1Staking.address, + arbAddressBookPath: taskArgs.arbitrumAddressBook, + chainId: graph.l2.chainId, + }) + + await setPausedBridge(graph.l1.contracts, l1Governor, { paused: false }) + await setPausedBridge(graph.l2.contracts, l2Governor, { paused: false }) + + console.log('Done!') + }) diff --git a/packages/contracts/tasks/migrate/nitro.ts b/packages/contracts/tasks/migrate/nitro.ts new file mode 100644 index 000000000..a399b5002 --- /dev/null +++ b/packages/contracts/tasks/migrate/nitro.ts @@ -0,0 +1,74 @@ +import { subtask, task } from 'hardhat/config' +import fs from 'fs' +import { execSync } from 'child_process' +import { greTask } from '@graphprotocol/sdk/gre' +import { helpers } from '@graphprotocol/sdk' + +greTask( + 'migrate:nitro:fund-accounts', + 'Funds protocol accounts on Arbitrum Nitro testnodes', +).setAction(async (taskArgs, hre) => { + const graph = hre.graph(taskArgs) + await helpers.fundLocalAccounts( + [await graph.getDeployer(), ...(await graph.getAllAccounts())], + graph.provider, + ) +}) + +// Arbitrum SDK does not support Nitro testnodes out of the box +// This adds the testnodes to the SDK configuration +subtask('migrate:nitro:register', 'Adds nitro testnodes to SDK config') + .addParam('deploymentFile', 'The testnode deployment file to use', 'localNetwork.json') + // eslint-disable-next-line @typescript-eslint/require-await + .setAction(async (taskArgs): Promise => { + helpers.addLocalNetwork(taskArgs.deploymentFile) + }) + +subtask('migrate:nitro:deployment-file', 'Fetches nitro deployment file from a local testnode') + .addParam( + 'deploymentFile', + 'Path to the file where to deployment file will be saved', + 'localNetwork.json', + ) + // eslint-disable-next-line @typescript-eslint/require-await + .setAction(async (taskArgs) => { + console.log(`Attempting to fetch deployment file from testnode...`) + + const command = `docker container cp $(docker ps -alqf "name=tokenbridge" --format "{{.ID}}"):/workspace/localNetwork.json .` + const stdOut = execSync(command) + console.log(stdOut.toString()) + + if (!fs.existsSync(taskArgs.deploymentFile)) { + throw new Error(`Unable to fetch deployment file: ${taskArgs.deploymentFile}`) + } + console.log(`Deployment file saved to ${taskArgs.deploymentFile}`) + }) + +// Read arbitrum contract addresses from deployment file and write them to the address book +task('migrate:nitro:address-book', 'Write arbitrum addresses to address book') + .addParam('deploymentFile', 'The testnode deployment file to use') + .addParam('arbitrumAddressBook', 'Arbitrum address book file') + .setAction(async (taskArgs, hre) => { + if (!fs.existsSync(taskArgs.deploymentFile)) { + await hre.run('migrate:nitro:deployment-file', taskArgs) + } + const deployment = JSON.parse(fs.readFileSync(taskArgs.deploymentFile, 'utf-8')) + + const addressBook = { + 1337: { + L1GatewayRouter: { + address: deployment.l2Network.tokenBridge.l1GatewayRouter, + }, + IInbox: { + address: deployment.l2Network.ethBridge.inbox, + }, + }, + 412346: { + L2GatewayRouter: { + address: deployment.l2Network.tokenBridge.l2GatewayRouter, + }, + }, + } + + fs.writeFileSync(taskArgs.arbitrumAddressBook, JSON.stringify(addressBook)) + }) diff --git a/packages/contracts/tasks/migrate/protocol.ts b/packages/contracts/tasks/migrate/protocol.ts new file mode 100644 index 000000000..38664a573 --- /dev/null +++ b/packages/contracts/tasks/migrate/protocol.ts @@ -0,0 +1,25 @@ +import { deployGraphNetwork, GraphChainId } from '@graphprotocol/sdk' +import { greTask } from '@graphprotocol/sdk/gre' + +greTask('migrate', 'Deploy protocol contracts') + .addFlag('skipConfirmation', 'Skip confirmation prompt on write actions') + .addFlag('skipPostDeploy', 'Skip accepting ownership and unpausing protocol after deploying') + .addFlag('force', 'Deploy contract even if its already deployed') + .addFlag('buildAcceptTx', '...') + .setAction(async (taskArgs, hre) => { + const graph = hre.graph(taskArgs) + + await deployGraphNetwork( + taskArgs.addressBook, + taskArgs.graphConfig, + graph.chainId as GraphChainId, // TODO: fix type + await graph.getDeployer(), + graph.provider, + { + governor: taskArgs.skipPostDeploy ? undefined : (await graph.getNamedAccounts()).governor, + forceDeploy: taskArgs.force, + skipConfirmation: taskArgs.skipConfirmation, + buildAcceptTx: taskArgs.buildAcceptTx, + }, + ) + }) diff --git a/packages/contracts/tasks/test-upgrade.ts b/packages/contracts/tasks/test-upgrade.ts index 93e45d43c..911d2ac75 100644 --- a/packages/contracts/tasks/test-upgrade.ts +++ b/packages/contracts/tasks/test-upgrade.ts @@ -24,7 +24,7 @@ const UPGRADEABLE_CONTRACTS: UpgradeableContract[] = [ ] task('test:upgrade-setup', 'Deploy contracts using an OZ proxy').setAction( - async (taskArgs, hre) => { + async (_, hre) => { const contractAddresses = {} for (const upgradeableContract of UPGRADEABLE_CONTRACTS) { // Deploy libraries diff --git a/packages/contracts/tasks/verify/defender.ts b/packages/contracts/tasks/verify/defender.ts index 68775afef..24ad83f59 100644 --- a/packages/contracts/tasks/verify/defender.ts +++ b/packages/contracts/tasks/verify/defender.ts @@ -7,7 +7,7 @@ import type { VerificationResponse } from '@openzeppelin/hardhat-defender/dist/v import { GraphNetworkContractName, isGraphNetworkContractName } from '@graphprotocol/sdk' async function main( - args: { referenceUrl?: string; contracts: GraphNetworkContractName[] }, + args: { referenceUrl?: string, contracts: GraphNetworkContractName[] }, hre: HRE, ) { const { referenceUrl, contracts } = args @@ -15,16 +15,16 @@ async function main( const summaryPath = process.env.GITHUB_STEP_SUMMARY if (summaryPath) appendFileSync(summaryPath, `# Contracts deployment verification\n\n`) - const workflowUrl = - referenceUrl || - process.env.WORKFLOW_URL || - execSync(`git config --get remote.origin.url`).toString().trim() + const workflowUrl + = referenceUrl + || process.env.WORKFLOW_URL + || execSync(`git config --get remote.origin.url`).toString().trim() const addressBook = graph().addressBook const errs = [] for (const contractName of contracts) { if (!isGraphNetworkContractName(contractName)) { - throw new Error(`Invalid contract name: ${contractName}`) + throw new Error(`Invalid contract name: ${contractName as string}`) } const entry = addressBook.getEntry(contractName) if (!entry || entry.address === constants.AddressZero) { @@ -49,7 +49,7 @@ async function main( if (response.matchType === 'NO_MATCH') { errs.push([contractName, { message: `No bytecode match.` }]) } - } catch (err: any) { + } catch (err) { if (summaryPath) { appendFileSync( summaryPath, diff --git a/packages/contracts/tasks/verify/sourcify.ts b/packages/contracts/tasks/verify/sourcify.ts index a872884bc..027885006 100644 --- a/packages/contracts/tasks/verify/sourcify.ts +++ b/packages/contracts/tasks/verify/sourcify.ts @@ -1,3 +1,4 @@ +/* eslint-disable no-secrets/no-secrets */ /* eslint-disable @typescript-eslint/no-explicit-any */ import axios from 'axios' import FormData from 'form-data' @@ -43,7 +44,7 @@ export async function submitSourcesToSourcify( return } } catch (e) { - console.error(((e as any).response && JSON.stringify((e as any).response.data)) || e) + console.error(((e).response && JSON.stringify((e).response.data)) || e) } console.log(`verifying ${contract.name} (${contract.address} on chain ${chainId}) ...`) @@ -72,6 +73,6 @@ export async function submitSourcesToSourcify( console.error(` => contract ${contract.name} is not verified`) } } catch (e) { - console.error(((e as any).response && JSON.stringify((e as any).response.data)) || e) + console.error(((e).response && JSON.stringify((e).response.data)) || e) } } diff --git a/packages/contracts/tasks/verify/verify.ts b/packages/contracts/tasks/verify/verify.ts index 40e8eadee..451409e12 100644 --- a/packages/contracts/tasks/verify/verify.ts +++ b/packages/contracts/tasks/verify/verify.ts @@ -3,11 +3,11 @@ import * as types from 'hardhat/internal/core/params/argumentTypes' import { submitSourcesToSourcify } from './sourcify' import { isFullyQualifiedName, parseFullyQualifiedName } from 'hardhat/utils/contract-names' import { TASK_COMPILE } from 'hardhat/builtin-tasks/task-names' -import { GRE_TASK_PARAMS } from '@graphprotocol/sdk/gre' +import { greTask } from '@graphprotocol/sdk/gre' import fs from 'fs' import path from 'path' import { HardhatRuntimeEnvironment } from 'hardhat/types/runtime' -import { getContractConfig } from '@graphprotocol/sdk' +import { getContractConfig, readConfig } from '@graphprotocol/sdk' task('sourcify', 'Verifies contract on sourcify') .addPositionalParam('address', 'Address of the smart contract to verify', undefined, types.string) @@ -32,115 +32,94 @@ task('sourcify', 'Verifies contract on sourcify') }) }) -task('sourcifyAll', 'Verifies all contracts on sourcify') - .addParam( - 'addressBook', - GRE_TASK_PARAMS.addressBook.description, - GRE_TASK_PARAMS.addressBook.default, - ) - .setAction(async (_args, hre) => { - const chainId = hre.network.config.chainId - const chainName = hre.network.name - - if (!chainId || !chainName) { - throw new Error('Cannot verify contracts without a network') - } - console.log(`> Verifying all contracts on chain ${chainName}[${chainId}]...`) - const { addressBook } = hre.graph({ addressBook: _args.addressBook }) +greTask('sourcifyAll', 'Verifies all contracts on sourcify').setAction(async (_args, hre) => { + const chainId = hre.network.config.chainId + const chainName = hre.network.name - for (const contractName of addressBook.listEntries()) { - console.log(`\n> Verifying contract ${contractName}...`) + if (!chainId || !chainName) { + throw new Error('Cannot verify contracts without a network') + } + console.log(`> Verifying all contracts on chain ${chainName}[${chainId}]...`) + const { addressBook } = hre.graph({ addressBook: _args.addressBook }) - const contractPath = getContractPath(contractName) - if (contractPath) { - const contract = addressBook.getEntry(contractName) - if (contract.implementation) { - console.log('Contract is upgradeable, verifying proxy...') + for (const contractName of addressBook.listEntries()) { + console.log(`\n> Verifying contract ${contractName}...`) - await hre.run('sourcify', { - address: contract.address, - contract: 'contracts/upgrades/GraphProxy.sol:GraphProxy', - }) - } + const contractPath = getContractPath(contractName) + if (contractPath) { + const contract = addressBook.getEntry(contractName) + if (contract.implementation) { + console.log('Contract is upgradeable, verifying proxy...') - // Verify implementation await hre.run('sourcify', { - address: contract.implementation?.address ?? contract.address, - contract: `${contractPath}:${contractName}`, + address: contract.address, + contract: 'contracts/upgrades/GraphProxy.sol:GraphProxy', }) - } else { - console.log(`Contract ${contractName} not found.`) } + + // Verify implementation + await hre.run('sourcify', { + address: contract.implementation?.address ?? contract.address, + contract: `${contractPath}:${contractName}`, + }) + } else { + console.log(`Contract ${contractName} not found.`) } + } +}) + +greTask('verifyAll', 'Verifies all contracts on etherscan').setAction(async (args, hre) => { + const chainId = hre.network.config.chainId + const chainName = hre.network.name + + if (!chainId || !chainName) { + throw new Error('Cannot verify contracts without a network') + } + + console.log(`> Verifying all contracts on chain ${chainName}[${chainId}]...`) + const { addressBook, getDeployer } = hre.graph({ + addressBook: args.addressBook, + graphConfig: args.graphConfig, }) + const graphConfig = readConfig(args.graphConfig, false) + const deployer = (await getDeployer()).address + for (const contractName of addressBook.listEntries()) { + console.log(`\n> Verifying contract ${contractName}...`) -task('verifyAll', 'Verifies all contracts on etherscan') - .addParam( - 'addressBook', - GRE_TASK_PARAMS.addressBook.description, - GRE_TASK_PARAMS.addressBook.default, - ) - .addParam( - 'graphConfig', - GRE_TASK_PARAMS.graphConfig.description, - GRE_TASK_PARAMS.graphConfig.default, - ) - .setAction(async (args, hre) => { - const chainId = hre.network.config.chainId - const chainName = hre.network.name + const contractConfig = getContractConfig(graphConfig, addressBook, contractName, deployer) + const contractPath = getContractPath(contractName) + const constructorParams = contractConfig.params.map(p => p.value.toString()) - if (!chainId || !chainName) { - throw new Error('Cannot verify contracts without a network') - } + if (contractPath) { + const contract = addressBook.getEntry(contractName) - console.log(`> Verifying all contracts on chain ${chainName}[${chainId}]...`) - const { addressBook, graphConfig, getDeployer } = hre.graph({ - addressBook: args.addressBook, - graphConfig: args.graphConfig, - }) + if (contract.implementation) { + console.log('Contract is upgradeable, verifying proxy...') + const proxyAdmin = addressBook.getEntry('GraphProxyAdmin') - for (const contractName of addressBook.listEntries()) { - console.log(`\n> Verifying contract ${contractName}...`) - - const contractConfig = getContractConfig( - graphConfig, - addressBook, - contractName, - (await getDeployer()).address, - ) - const contractPath = getContractPath(contractName) - const constructorParams = contractConfig.params.map((p) => p.value.toString()) - - if (contractPath) { - const contract = addressBook.getEntry(contractName) - - if (contract.implementation) { - console.log('Contract is upgradeable, verifying proxy...') - const proxyAdmin = addressBook.getEntry('GraphProxyAdmin') - - // Verify proxy - await safeVerify(hre, { - address: contract.address, - contract: 'contracts/upgrades/GraphProxy.sol:GraphProxy', - constructorArgsParams: [contract.implementation.address, proxyAdmin.address], - }) - } - - // Verify implementation - console.log('Verifying implementation...') + // Verify proxy await safeVerify(hre, { - address: contract.implementation?.address ?? contract.address, - contract: `${contractPath}:${contractName}`, - constructorArgsParams: contract.implementation ? [] : constructorParams, + address: contract.address, + contract: 'contracts/upgrades/GraphProxy.sol:GraphProxy', + constructorArgsParams: [contract.implementation.address, proxyAdmin.address], }) - } else { - console.log(`Contract ${contractName} not found.`) } + + // Verify implementation + console.log('Verifying implementation...') + await safeVerify(hre, { + address: contract.implementation?.address ?? contract.address, + contract: `${contractPath}:${contractName}`, + constructorArgsParams: contract.implementation ? [] : constructorParams, + }) + } else { + console.log(`Contract ${contractName} not found.`) } - }) + } +}) // etherscan API throws errors if the contract is already verified -async function safeVerify(hre: HardhatRuntimeEnvironment, taskArguments: any): Promise { +async function safeVerify(hre: HardhatRuntimeEnvironment, taskArguments: unknown): Promise { try { await hre.run('verify', taskArguments) } catch (error) { @@ -150,7 +129,7 @@ async function safeVerify(hre: HardhatRuntimeEnvironment, taskArguments: any): P function getContractPath(contract: string): string | undefined { const files = readDirRecursive('contracts/') - return files.find((f) => path.basename(f) === `${contract}.sol`) + return files.find(f => path.basename(f) === `${contract}.sol`) } function readDirRecursive(dir: string, allFiles: string[] = []) { diff --git a/packages/contracts/e2e/deployment/config/allocationExchange.test.ts b/packages/contracts/test/e2e/deployment/config/allocationExchange.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/allocationExchange.test.ts rename to packages/contracts/test/e2e/deployment/config/allocationExchange.test.ts diff --git a/packages/contracts/e2e/deployment/config/controller.test.ts b/packages/contracts/test/e2e/deployment/config/controller.test.ts similarity index 97% rename from packages/contracts/e2e/deployment/config/controller.test.ts rename to packages/contracts/test/e2e/deployment/config/controller.test.ts index 820864542..fea7eadc2 100644 --- a/packages/contracts/e2e/deployment/config/controller.test.ts +++ b/packages/contracts/test/e2e/deployment/config/controller.test.ts @@ -60,7 +60,7 @@ describe('Controller configuration', () => { expect(pauseGuardian).eq(namedAccounts.pauseGuardian.address) }) - describe('proxy contract', async function () { + describe('proxy contract', function () { const proxyContracts = isGraphL1ChainId(graph.chainId) ? l1ProxyContracts : l2ProxyContracts for (const contract of proxyContracts) { it(`${contract} should match deployed`, async function () { diff --git a/packages/contracts/e2e/deployment/config/disputeManager.test.ts b/packages/contracts/test/e2e/deployment/config/disputeManager.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/disputeManager.test.ts rename to packages/contracts/test/e2e/deployment/config/disputeManager.test.ts diff --git a/packages/contracts/e2e/deployment/config/epochManager.test.ts b/packages/contracts/test/e2e/deployment/config/epochManager.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/epochManager.test.ts rename to packages/contracts/test/e2e/deployment/config/epochManager.test.ts diff --git a/packages/contracts/e2e/deployment/config/gns.test.ts b/packages/contracts/test/e2e/deployment/config/gns.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/gns.test.ts rename to packages/contracts/test/e2e/deployment/config/gns.test.ts diff --git a/packages/contracts/e2e/deployment/config/graphProxyAdmin.test.ts b/packages/contracts/test/e2e/deployment/config/graphProxyAdmin.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/graphProxyAdmin.test.ts rename to packages/contracts/test/e2e/deployment/config/graphProxyAdmin.test.ts diff --git a/packages/contracts/e2e/deployment/config/graphToken.test.ts b/packages/contracts/test/e2e/deployment/config/graphToken.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/graphToken.test.ts rename to packages/contracts/test/e2e/deployment/config/graphToken.test.ts diff --git a/packages/contracts/e2e/deployment/config/l1/bridgeEscrow.test.ts b/packages/contracts/test/e2e/deployment/config/l1/bridgeEscrow.test.ts similarity index 94% rename from packages/contracts/e2e/deployment/config/l1/bridgeEscrow.test.ts rename to packages/contracts/test/e2e/deployment/config/l1/bridgeEscrow.test.ts index 9d6fd606b..bea48aea6 100644 --- a/packages/contracts/e2e/deployment/config/l1/bridgeEscrow.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l1/bridgeEscrow.test.ts @@ -6,7 +6,7 @@ describe('[L1] BridgeEscrow configuration', function () { const graph = hre.graph() const { Controller, BridgeEscrow } = graph.contracts - before(async function () { + before(function () { if (isGraphL2ChainId(graph.chainId)) this.skip() }) diff --git a/packages/contracts/e2e/deployment/config/l1/curation.test.ts b/packages/contracts/test/e2e/deployment/config/l1/curation.test.ts similarity index 98% rename from packages/contracts/e2e/deployment/config/l1/curation.test.ts rename to packages/contracts/test/e2e/deployment/config/l1/curation.test.ts index 1b7492506..f0fa363c5 100644 --- a/packages/contracts/e2e/deployment/config/l1/curation.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l1/curation.test.ts @@ -9,7 +9,7 @@ describe('[L1] Curation configuration', () => { contracts: { Controller, Curation, BancorFormula, GraphCurationToken }, } = graph - before(async function () { + before(function () { if (isGraphL2ChainId(graph.chainId)) this.skip() }) diff --git a/packages/contracts/e2e/deployment/config/l1/graphToken.test.ts b/packages/contracts/test/e2e/deployment/config/l1/graphToken.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/l1/graphToken.test.ts rename to packages/contracts/test/e2e/deployment/config/l1/graphToken.test.ts diff --git a/packages/contracts/e2e/deployment/config/l1/l1GNS.test.ts b/packages/contracts/test/e2e/deployment/config/l1/l1GNS.test.ts similarity index 78% rename from packages/contracts/e2e/deployment/config/l1/l1GNS.test.ts rename to packages/contracts/test/e2e/deployment/config/l1/l1GNS.test.ts index 5a8fe8924..e33934d5e 100644 --- a/packages/contracts/e2e/deployment/config/l1/l1GNS.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l1/l1GNS.test.ts @@ -1,4 +1,3 @@ -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' import hre from 'hardhat' import { isGraphL2ChainId } from '@graphprotocol/sdk' @@ -7,11 +6,8 @@ describe('[L1] GNS', () => { const graph = hre.graph() const { L1GNS, L1GraphTokenGateway } = graph.contracts - let unauthorized: SignerWithAddress - - before(async function () { + before(function () { if (isGraphL2ChainId(graph.chainId)) this.skip() - unauthorized = (await graph.getTestAccounts())[0] }) describe('L1GNS', () => { diff --git a/packages/contracts/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts b/packages/contracts/test/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts similarity index 95% rename from packages/contracts/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts rename to packages/contracts/test/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts index be55d9bfe..e188fc89e 100644 --- a/packages/contracts/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l1/l1GraphTokenGateway.test.ts @@ -1,7 +1,7 @@ import { expect } from 'chai' import hre from 'hardhat' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { SimpleAddressBook, isGraphL2ChainId } from '@graphprotocol/sdk' +import { isGraphL2ChainId, SimpleAddressBook } from '@graphprotocol/sdk' describe('[L1] L1GraphTokenGateway configuration', function () { const graph = hre.graph() @@ -38,7 +38,7 @@ describe('[L1] L1GraphTokenGateway configuration', function () { expect(escrow).eq(graph.l1.contracts.BridgeEscrow.address) }) - it("inbox should match Arbitrum's Inbox address", async function () { + it('inbox should match Arbitrum\'s Inbox address', async function () { const inbox = await L1GraphTokenGateway.inbox() const arbitrumAddressBook = process.env.ARBITRUM_ADDRESS_BOOK ?? 'arbitrum-addresses-local.json' const arbAddressBook = new SimpleAddressBook(arbitrumAddressBook, graph.l1.chainId) @@ -47,7 +47,7 @@ describe('[L1] L1GraphTokenGateway configuration', function () { expect(inbox.toLowerCase()).eq(arbIInbox.address.toLowerCase()) }) - it("l1Router should match Arbitrum's router address", async function () { + it('l1Router should match Arbitrum\'s router address', async function () { const l1Router = await L1GraphTokenGateway.l1Router() const arbitrumAddressBook = process.env.ARBITRUM_ADDRESS_BOOK ?? 'arbitrum-addresses-local.json' const arbAddressBook = new SimpleAddressBook(arbitrumAddressBook, graph.l1.chainId) diff --git a/packages/contracts/e2e/deployment/config/l1/l1Staking.test.ts b/packages/contracts/test/e2e/deployment/config/l1/l1Staking.test.ts similarity index 83% rename from packages/contracts/e2e/deployment/config/l1/l1Staking.test.ts rename to packages/contracts/test/e2e/deployment/config/l1/l1Staking.test.ts index 25d0b3805..185f2a2fe 100644 --- a/packages/contracts/e2e/deployment/config/l1/l1Staking.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l1/l1Staking.test.ts @@ -1,4 +1,3 @@ -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' import hre from 'hardhat' import { isGraphL2ChainId } from '@graphprotocol/sdk' @@ -7,11 +6,8 @@ describe('[L1] Staking', () => { const graph = hre.graph() const { L1Staking, L1GraphTokenGateway } = graph.contracts - let unauthorized: SignerWithAddress - - before(async function () { + before(function () { if (isGraphL2ChainId(graph.chainId)) this.skip() - unauthorized = (await graph.getTestAccounts())[0] }) describe('L1Staking', () => { diff --git a/packages/contracts/e2e/deployment/config/l1/rewardsManager.test.ts b/packages/contracts/test/e2e/deployment/config/l1/rewardsManager.test.ts similarity index 95% rename from packages/contracts/e2e/deployment/config/l1/rewardsManager.test.ts rename to packages/contracts/test/e2e/deployment/config/l1/rewardsManager.test.ts index afc9287d6..0f9807d92 100644 --- a/packages/contracts/e2e/deployment/config/l1/rewardsManager.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l1/rewardsManager.test.ts @@ -6,7 +6,7 @@ describe('[L1] RewardsManager configuration', () => { const graph = hre.graph() const { RewardsManager } = graph.contracts - before(async function () { + before(function () { if (isGraphL2ChainId(graph.chainId)) this.skip() }) diff --git a/packages/contracts/e2e/deployment/config/l2/l2Curation.test.ts b/packages/contracts/test/e2e/deployment/config/l2/l2Curation.test.ts similarity index 98% rename from packages/contracts/e2e/deployment/config/l2/l2Curation.test.ts rename to packages/contracts/test/e2e/deployment/config/l2/l2Curation.test.ts index 3722b6b14..b38f679a6 100644 --- a/packages/contracts/e2e/deployment/config/l2/l2Curation.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l2/l2Curation.test.ts @@ -9,7 +9,7 @@ describe('[L2] L2Curation configuration', () => { contracts: { Controller, L2Curation, GraphCurationToken }, } = graph - before(async function () { + before(function () { if (isGraphL1ChainId(graph.chainId)) this.skip() }) diff --git a/packages/contracts/e2e/deployment/config/l2/l2GNS.test.ts b/packages/contracts/test/e2e/deployment/config/l2/l2GNS.test.ts similarity index 72% rename from packages/contracts/e2e/deployment/config/l2/l2GNS.test.ts rename to packages/contracts/test/e2e/deployment/config/l2/l2GNS.test.ts index 133d77077..2ebd7cf5e 100644 --- a/packages/contracts/e2e/deployment/config/l2/l2GNS.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l2/l2GNS.test.ts @@ -1,4 +1,3 @@ -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' import hre from 'hardhat' import { isGraphL1ChainId } from '@graphprotocol/sdk' @@ -7,11 +6,8 @@ describe('[L2] GNS', () => { const graph = hre.graph() const { L2GNS } = graph.l2.contracts - let unauthorized: SignerWithAddress - - before(async function () { + before(function () { if (isGraphL1ChainId(graph.chainId)) this.skip() - unauthorized = (await graph.getTestAccounts())[0] }) describe('L2GNS', () => { diff --git a/packages/contracts/e2e/deployment/config/l2/l2GraphToken.test.ts b/packages/contracts/test/e2e/deployment/config/l2/l2GraphToken.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/l2/l2GraphToken.test.ts rename to packages/contracts/test/e2e/deployment/config/l2/l2GraphToken.test.ts diff --git a/packages/contracts/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts b/packages/contracts/test/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts similarity index 95% rename from packages/contracts/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts rename to packages/contracts/test/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts index 45033cb28..cae73cbd9 100644 --- a/packages/contracts/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l2/l2GraphTokenGateway.test.ts @@ -1,7 +1,7 @@ import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' import hre from 'hardhat' -import { SimpleAddressBook, isGraphL1ChainId } from '@graphprotocol/sdk' +import { isGraphL1ChainId, SimpleAddressBook } from '@graphprotocol/sdk' describe('[L2] L2GraphTokenGateway configuration', function () { const graph = hre.graph() @@ -33,7 +33,7 @@ describe('[L2] L2GraphTokenGateway configuration', function () { expect(l1Counterpart).eq(graph.l1.contracts.L1GraphTokenGateway.address) }) - it("l2Router should match Arbitrum's router address", async function () { + it('l2Router should match Arbitrum\'s router address', async function () { const l2Router = await L2GraphTokenGateway.l2Router() // TODO: is there a cleaner way to get the router address? diff --git a/packages/contracts/e2e/deployment/config/l2/l2Staking.test.ts b/packages/contracts/test/e2e/deployment/config/l2/l2Staking.test.ts similarity index 79% rename from packages/contracts/e2e/deployment/config/l2/l2Staking.test.ts rename to packages/contracts/test/e2e/deployment/config/l2/l2Staking.test.ts index 0e81d9892..dda82fd85 100644 --- a/packages/contracts/e2e/deployment/config/l2/l2Staking.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l2/l2Staking.test.ts @@ -1,4 +1,3 @@ -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { expect } from 'chai' import hre from 'hardhat' import { isGraphL1ChainId } from '@graphprotocol/sdk' @@ -7,11 +6,8 @@ describe('[L2] Staking', () => { const graph = hre.graph() const { L2Staking } = graph.l2.contracts - let unauthorized: SignerWithAddress - - before(async function () { + before(function () { if (isGraphL1ChainId(graph.chainId)) this.skip() - unauthorized = (await graph.getTestAccounts())[0] }) describe('L2Staking', () => { diff --git a/packages/contracts/e2e/deployment/config/l2/rewardsManager.test.ts b/packages/contracts/test/e2e/deployment/config/l2/rewardsManager.test.ts similarity index 94% rename from packages/contracts/e2e/deployment/config/l2/rewardsManager.test.ts rename to packages/contracts/test/e2e/deployment/config/l2/rewardsManager.test.ts index a2846001e..9759ba78d 100644 --- a/packages/contracts/e2e/deployment/config/l2/rewardsManager.test.ts +++ b/packages/contracts/test/e2e/deployment/config/l2/rewardsManager.test.ts @@ -6,7 +6,7 @@ describe('[L2] RewardsManager configuration', () => { const graph = hre.graph() const { RewardsManager } = graph.contracts - before(async function () { + before(function () { if (isGraphL1ChainId(graph.chainId)) this.skip() }) diff --git a/packages/contracts/e2e/deployment/config/rewardsManager.test.ts b/packages/contracts/test/e2e/deployment/config/rewardsManager.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/rewardsManager.test.ts rename to packages/contracts/test/e2e/deployment/config/rewardsManager.test.ts diff --git a/packages/contracts/e2e/deployment/config/serviceRegistry.test..ts b/packages/contracts/test/e2e/deployment/config/serviceRegistry.test..ts similarity index 100% rename from packages/contracts/e2e/deployment/config/serviceRegistry.test..ts rename to packages/contracts/test/e2e/deployment/config/serviceRegistry.test..ts diff --git a/packages/contracts/e2e/deployment/config/staking.test.ts b/packages/contracts/test/e2e/deployment/config/staking.test.ts similarity index 98% rename from packages/contracts/e2e/deployment/config/staking.test.ts rename to packages/contracts/test/e2e/deployment/config/staking.test.ts index 2d93da605..cfd4110b4 100644 --- a/packages/contracts/e2e/deployment/config/staking.test.ts +++ b/packages/contracts/test/e2e/deployment/config/staking.test.ts @@ -5,7 +5,7 @@ import { getItemValue, isGraphL2ChainId } from '@graphprotocol/sdk' describe('Staking configuration', () => { const { graphConfig, - contracts: { Staking, Controller, DisputeManager, AllocationExchange }, + contracts: { Staking, Controller, DisputeManager }, chainId, } = hre.graph() let contractName: string diff --git a/packages/contracts/e2e/deployment/config/subgraphNFT.test.ts b/packages/contracts/test/e2e/deployment/config/subgraphNFT.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/config/subgraphNFT.test.ts rename to packages/contracts/test/e2e/deployment/config/subgraphNFT.test.ts diff --git a/packages/contracts/e2e/deployment/init/allocationExchange.test.ts b/packages/contracts/test/e2e/deployment/init/allocationExchange.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/init/allocationExchange.test.ts rename to packages/contracts/test/e2e/deployment/init/allocationExchange.test.ts diff --git a/packages/contracts/e2e/deployment/init/gns.test.ts b/packages/contracts/test/e2e/deployment/init/gns.test.ts similarity index 100% rename from packages/contracts/e2e/deployment/init/gns.test.ts rename to packages/contracts/test/e2e/deployment/init/gns.test.ts diff --git a/packages/contracts/e2e/deployment/init/l1/bridgeEscrow.test.ts b/packages/contracts/test/e2e/deployment/init/l1/bridgeEscrow.test.ts similarity index 76% rename from packages/contracts/e2e/deployment/init/l1/bridgeEscrow.test.ts rename to packages/contracts/test/e2e/deployment/init/l1/bridgeEscrow.test.ts index 98e64d5ab..0abb37278 100644 --- a/packages/contracts/e2e/deployment/init/l1/bridgeEscrow.test.ts +++ b/packages/contracts/test/e2e/deployment/init/l1/bridgeEscrow.test.ts @@ -6,11 +6,11 @@ describe('[L1] BridgeEscrow initialization', () => { const graph = hre.graph() const { BridgeEscrow, GraphToken, L1GraphTokenGateway } = graph.contracts - before(async function () { + before(function () { if (isGraphL2ChainId(graph.chainId)) this.skip() }) - it("should allow L1GraphTokenGateway contract to spend MAX_UINT256 tokens on BridgeEscrow's behalf", async function () { + it('should allow L1GraphTokenGateway contract to spend MAX_UINT256 tokens on BridgeEscrow\'s behalf', async function () { const allowance = await GraphToken.allowance(BridgeEscrow.address, L1GraphTokenGateway.address) expect(allowance).eq(hre.ethers.constants.MaxUint256) }) diff --git a/packages/contracts/e2e/deployment/init/l1/graphToken.test.ts b/packages/contracts/test/e2e/deployment/init/l1/graphToken.test.ts similarity index 95% rename from packages/contracts/e2e/deployment/init/l1/graphToken.test.ts rename to packages/contracts/test/e2e/deployment/init/l1/graphToken.test.ts index be95373c5..87ad5769a 100644 --- a/packages/contracts/e2e/deployment/init/l1/graphToken.test.ts +++ b/packages/contracts/test/e2e/deployment/init/l1/graphToken.test.ts @@ -6,7 +6,7 @@ describe('[L1] GraphToken initialization', () => { const graph = hre.graph() const { GraphToken } = graph.contracts - before(async function () { + before(function () { if (isGraphL2ChainId(graph.chainId)) this.skip() }) diff --git a/packages/contracts/e2e/deployment/init/l2/graphToken.test.ts b/packages/contracts/test/e2e/deployment/init/l2/graphToken.test.ts similarity index 93% rename from packages/contracts/e2e/deployment/init/l2/graphToken.test.ts rename to packages/contracts/test/e2e/deployment/init/l2/graphToken.test.ts index 2debc22d7..c7978ac81 100644 --- a/packages/contracts/e2e/deployment/init/l2/graphToken.test.ts +++ b/packages/contracts/test/e2e/deployment/init/l2/graphToken.test.ts @@ -6,7 +6,7 @@ describe('[L2] GraphToken initialization', () => { const graph = hre.graph() const { GraphToken } = graph.contracts - before(async function () { + before(function () { if (isGraphL1ChainId(graph.chainId)) this.skip() }) diff --git a/packages/contracts/e2e/scenarios/close-allocations.test.ts b/packages/contracts/test/e2e/scenarios/close-allocations.test.ts similarity index 84% rename from packages/contracts/e2e/scenarios/close-allocations.test.ts rename to packages/contracts/test/e2e/scenarios/close-allocations.test.ts index efbb18004..a8ace4c7c 100644 --- a/packages/contracts/e2e/scenarios/close-allocations.test.ts +++ b/packages/contracts/test/e2e/scenarios/close-allocations.test.ts @@ -23,10 +23,10 @@ describe('Close allocations', () => { let openAllocations: AllocationFixture[] = [] let closedAllocations: AllocationFixture[] = [] - before(async () => { - allocations = indexerFixtures.map((i) => i.allocations).flat() - openAllocations = allocations.filter((a) => !a.close) - closedAllocations = allocations.filter((a) => a.close) + before(() => { + allocations = indexerFixtures.map(i => i.allocations).flat() + openAllocations = allocations.filter(a => !a.close) + closedAllocations = allocations.filter(a => a.close) }) it(`some allocatons should be open`, async function () { diff --git a/packages/contracts/e2e/scenarios/close-allocations.ts b/packages/contracts/test/e2e/scenarios/close-allocations.ts similarity index 89% rename from packages/contracts/e2e/scenarios/close-allocations.ts rename to packages/contracts/test/e2e/scenarios/close-allocations.ts index f37589230..96c59174b 100644 --- a/packages/contracts/e2e/scenarios/close-allocations.ts +++ b/packages/contracts/test/e2e/scenarios/close-allocations.ts @@ -9,7 +9,7 @@ import hre from 'hardhat' import { getIndexerFixtures } from './fixtures/indexers' -import { helpers, closeAllocation } from '@graphprotocol/sdk' +import { closeAllocation, helpers } from '@graphprotocol/sdk' import { getGREOptsFromArgv } from '@graphprotocol/sdk/gre' @@ -18,7 +18,7 @@ async function main() { const graph = hre.graph(graphOpts) const indexerFixtures = getIndexerFixtures(await graph.getTestAccounts()) - const ethBalances = indexerFixtures.map((i) => ({ + const ethBalances = indexerFixtures.map(i => ({ address: i.signer.address, balance: i.ethBalance, })) @@ -37,7 +37,7 @@ async function main() { console.log('\n== Close allocations') for (const indexer of indexerFixtures) { - for (const allocation of indexer.allocations.filter((a) => a.close)) { + for (const allocation of indexer.allocations.filter(a => a.close)) { await closeAllocation(graph.contracts, indexer.signer, { allocationId: allocation.signer.address, }) diff --git a/packages/contracts/e2e/scenarios/create-subgraphs.test.ts b/packages/contracts/test/e2e/scenarios/create-subgraphs.test.ts similarity index 94% rename from packages/contracts/e2e/scenarios/create-subgraphs.test.ts rename to packages/contracts/test/e2e/scenarios/create-subgraphs.test.ts index b2ece4dd8..055093dc6 100644 --- a/packages/contracts/e2e/scenarios/create-subgraphs.test.ts +++ b/packages/contracts/test/e2e/scenarios/create-subgraphs.test.ts @@ -3,7 +3,7 @@ import hre from 'hardhat' import { recreatePreviousSubgraphId } from '@graphprotocol/sdk' import { BigNumber } from 'ethers' import { CuratorFixture, getCuratorFixtures } from './fixtures/curators' -import { SubgraphFixture, getSubgraphFixtures, getSubgraphOwner } from './fixtures/subgraphs' +import { getSubgraphFixtures, getSubgraphOwner, SubgraphFixture } from './fixtures/subgraphs' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' let curatorFixtures: CuratorFixture[] @@ -55,7 +55,7 @@ describe('Publish subgraphs', () => { let totalSignal: BigNumber = BigNumber.from(0) for (const curator of curatorFixtures) { - const _subgraph = curator.subgraphs.find((s) => s.deploymentId === subgraph.deploymentId) + const _subgraph = curator.subgraphs.find(s => s.deploymentId === subgraph.deploymentId) if (_subgraph) { totalSignal = totalSignal.add(_subgraph.signal) } diff --git a/packages/contracts/e2e/scenarios/create-subgraphs.ts b/packages/contracts/test/e2e/scenarios/create-subgraphs.ts similarity index 85% rename from packages/contracts/e2e/scenarios/create-subgraphs.ts rename to packages/contracts/test/e2e/scenarios/create-subgraphs.ts index 09306b059..9f2486ff7 100644 --- a/packages/contracts/e2e/scenarios/create-subgraphs.ts +++ b/packages/contracts/test/e2e/scenarios/create-subgraphs.ts @@ -8,7 +8,7 @@ import hre from 'hardhat' import { getSubgraphFixtures, getSubgraphOwner } from './fixtures/subgraphs' import { getCuratorFixtures } from './fixtures/curators' import { getGREOptsFromArgv } from '@graphprotocol/sdk/gre' -import { helpers, publishNewSubgraph, mintSignal, setGRTBalances } from '@graphprotocol/sdk' +import { helpers, mintSignal, publishNewSubgraph, setGRTBalances } from '@graphprotocol/sdk' async function main() { const graphOpts = getGREOptsFromArgv() @@ -26,8 +26,8 @@ async function main() { balance: subgraphOwnerFixture.ethBalance, }, ] - curatorFixtures.map((c) => ethBalances.push({ address: c.signer.address, balance: c.ethBalance })) - const grtBalances = curatorFixtures.map((c) => ({ + curatorFixtures.map(c => ethBalances.push({ address: c.signer.address, balance: c.ethBalance })) + const grtBalances = curatorFixtures.map(c => ({ address: c.signer.address, balance: c.grtBalance, })) @@ -45,7 +45,7 @@ async function main() { deploymentId: subgraph.deploymentId, chainId: graph.chainId, }) - const subgraphData = subgraphFixtures.find((s) => s.deploymentId === subgraph.deploymentId) + const subgraphData = subgraphFixtures.find(s => s.deploymentId === subgraph.deploymentId) if (subgraphData) subgraphData.subgraphId = id } @@ -53,7 +53,7 @@ async function main() { console.log('\n== Signaling subgraphs') for (const curator of curatorFixtures) { for (const subgraph of curator.subgraphs) { - const subgraphData = subgraphFixtures.find((s) => s.deploymentId === subgraph.deploymentId) + const subgraphData = subgraphFixtures.find(s => s.deploymentId === subgraph.deploymentId) if (subgraphData) await mintSignal(graph.contracts, curator.signer, { subgraphId: subgraphData.subgraphId, diff --git a/packages/contracts/e2e/scenarios/fixtures/bridge.ts b/packages/contracts/test/e2e/scenarios/fixtures/bridge.ts similarity index 100% rename from packages/contracts/e2e/scenarios/fixtures/bridge.ts rename to packages/contracts/test/e2e/scenarios/fixtures/bridge.ts diff --git a/packages/contracts/e2e/scenarios/fixtures/curators.ts b/packages/contracts/test/e2e/scenarios/fixtures/curators.ts similarity index 100% rename from packages/contracts/e2e/scenarios/fixtures/curators.ts rename to packages/contracts/test/e2e/scenarios/fixtures/curators.ts diff --git a/packages/contracts/e2e/scenarios/fixtures/indexers.ts b/packages/contracts/test/e2e/scenarios/fixtures/indexers.ts similarity index 100% rename from packages/contracts/e2e/scenarios/fixtures/indexers.ts rename to packages/contracts/test/e2e/scenarios/fixtures/indexers.ts diff --git a/packages/contracts/e2e/scenarios/fixtures/subgraphs.ts b/packages/contracts/test/e2e/scenarios/fixtures/subgraphs.ts similarity index 100% rename from packages/contracts/e2e/scenarios/fixtures/subgraphs.ts rename to packages/contracts/test/e2e/scenarios/fixtures/subgraphs.ts diff --git a/packages/contracts/e2e/scenarios/open-allocations.test.ts b/packages/contracts/test/e2e/scenarios/open-allocations.test.ts similarity index 91% rename from packages/contracts/e2e/scenarios/open-allocations.test.ts rename to packages/contracts/test/e2e/scenarios/open-allocations.test.ts index a8c209133..159e81505 100644 --- a/packages/contracts/e2e/scenarios/open-allocations.test.ts +++ b/packages/contracts/test/e2e/scenarios/open-allocations.test.ts @@ -35,8 +35,8 @@ describe('Open allocations', () => { }) describe('Allocations', () => { - it(`allocatons should be open`, async function () { - const allocations = indexerFixtures.map((i) => i.allocations).flat() + it(`allocations should be open`, async function () { + const allocations = indexerFixtures.map(i => i.allocations).flat() for (const allocation of allocations) { const state = await Staking.getAllocationState(allocation.signer.address) expect(state).eq(AllocationState.Active) diff --git a/packages/contracts/e2e/scenarios/open-allocations.ts b/packages/contracts/test/e2e/scenarios/open-allocations.ts similarity index 90% rename from packages/contracts/e2e/scenarios/open-allocations.ts rename to packages/contracts/test/e2e/scenarios/open-allocations.ts index 2d971224e..8beac8d99 100644 --- a/packages/contracts/e2e/scenarios/open-allocations.ts +++ b/packages/contracts/test/e2e/scenarios/open-allocations.ts @@ -7,7 +7,7 @@ import hre from 'hardhat' import { getIndexerFixtures } from './fixtures/indexers' import { getGREOptsFromArgv } from '@graphprotocol/sdk/gre' -import { helpers, allocateFrom, stake, setGRTBalances } from '@graphprotocol/sdk' +import { allocateFrom, helpers, setGRTBalances, stake } from '@graphprotocol/sdk' async function main() { const graphOpts = getGREOptsFromArgv() @@ -15,11 +15,11 @@ async function main() { const indexerFixtures = getIndexerFixtures(await graph.getTestAccounts()) const deployer = await graph.getDeployer() - const indexerETHBalances = indexerFixtures.map((i) => ({ + const indexerETHBalances = indexerFixtures.map(i => ({ address: i.signer.address, balance: i.ethBalance, })) - const indexerGRTBalances = indexerFixtures.map((i) => ({ + const indexerGRTBalances = indexerFixtures.map(i => ({ address: i.signer.address, balance: i.grtBalance, })) diff --git a/packages/contracts/e2e/scenarios/send-grt-to-l2.test.ts b/packages/contracts/test/e2e/scenarios/send-grt-to-l2.test.ts similarity index 91% rename from packages/contracts/e2e/scenarios/send-grt-to-l2.test.ts rename to packages/contracts/test/e2e/scenarios/send-grt-to-l2.test.ts index 9b81371b6..3cb5ba83e 100644 --- a/packages/contracts/e2e/scenarios/send-grt-to-l2.test.ts +++ b/packages/contracts/test/e2e/scenarios/send-grt-to-l2.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai' import hre from 'hardhat' -import { getBridgeFixture, BridgeFixture } from './fixtures/bridge' +import { BridgeFixture, getBridgeFixture } from './fixtures/bridge' describe('Bridge GRT to L2', () => { const graph = hre.graph() diff --git a/packages/contracts/e2e/scenarios/send-grt-to-l2.ts b/packages/contracts/test/e2e/scenarios/send-grt-to-l2.ts similarity index 92% rename from packages/contracts/e2e/scenarios/send-grt-to-l2.ts rename to packages/contracts/test/e2e/scenarios/send-grt-to-l2.ts index 9a462cb91..d654866fd 100644 --- a/packages/contracts/e2e/scenarios/send-grt-to-l2.ts +++ b/packages/contracts/test/e2e/scenarios/send-grt-to-l2.ts @@ -5,7 +5,6 @@ // npx hardhat e2e:scenario send-grt-to-l2 --network --graph-config config/graph..yml import hre from 'hardhat' -import { TASK_BRIDGE_TO_L2 } from '../../tasks/bridge/to-l2' import { getBridgeFixture } from './fixtures/bridge' import { getGREOptsFromArgv } from '@graphprotocol/sdk/gre' import { ethers } from 'ethers' @@ -21,7 +20,7 @@ async function main() { // == Send GRT to L2 accounts for (const account of bridgeFixture.accountsToFund) { - await hre.run(TASK_BRIDGE_TO_L2, { + await hre.run('bridge:send-to-l2', { ...graphOpts, amount: ethers.utils.formatEther(account.amount), sender: bridgeFixture.funder.address, diff --git a/packages/contracts/e2e/upgrades/example/Instructions.md b/packages/contracts/test/e2e/upgrades/example/Instructions.md similarity index 100% rename from packages/contracts/e2e/upgrades/example/Instructions.md rename to packages/contracts/test/e2e/upgrades/example/Instructions.md diff --git a/packages/contracts/e2e/upgrades/example/post-upgrade.test.ts b/packages/contracts/test/e2e/upgrades/example/post-upgrade.test.ts similarity index 100% rename from packages/contracts/e2e/upgrades/example/post-upgrade.test.ts rename to packages/contracts/test/e2e/upgrades/example/post-upgrade.test.ts diff --git a/packages/contracts/e2e/upgrades/example/post-upgrade.ts b/packages/contracts/test/e2e/upgrades/example/post-upgrade.ts similarity index 77% rename from packages/contracts/e2e/upgrades/example/post-upgrade.ts rename to packages/contracts/test/e2e/upgrades/example/post-upgrade.ts index b3617dc23..ecd2ca395 100644 --- a/packages/contracts/e2e/upgrades/example/post-upgrade.ts +++ b/packages/contracts/test/e2e/upgrades/example/post-upgrade.ts @@ -1,3 +1,7 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/require-await */ +// REMOVE the above lines + import hre from 'hardhat' import { getGREOptsFromArgv } from '@graphprotocol/sdk/gre' diff --git a/packages/contracts/e2e/upgrades/example/pre-upgrade.test.ts b/packages/contracts/test/e2e/upgrades/example/pre-upgrade.test.ts similarity index 100% rename from packages/contracts/e2e/upgrades/example/pre-upgrade.test.ts rename to packages/contracts/test/e2e/upgrades/example/pre-upgrade.test.ts diff --git a/packages/contracts/e2e/upgrades/example/pre-upgrade.ts b/packages/contracts/test/e2e/upgrades/example/pre-upgrade.ts similarity index 77% rename from packages/contracts/e2e/upgrades/example/pre-upgrade.ts rename to packages/contracts/test/e2e/upgrades/example/pre-upgrade.ts index 12984e5c6..affbfc34d 100644 --- a/packages/contracts/e2e/upgrades/example/pre-upgrade.ts +++ b/packages/contracts/test/e2e/upgrades/example/pre-upgrade.ts @@ -1,3 +1,7 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/* eslint-disable @typescript-eslint/require-await */ +// REMOVE the above lines + import hre from 'hardhat' import { getGREOptsFromArgv } from '@graphprotocol/sdk/gre' diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/Instructions.md b/packages/contracts/test/e2e/upgrades/exponential-rebates/Instructions.md similarity index 100% rename from packages/contracts/e2e/upgrades/exponential-rebates/Instructions.md rename to packages/contracts/test/e2e/upgrades/exponential-rebates/Instructions.md diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/abis/staking.ts b/packages/contracts/test/e2e/upgrades/exponential-rebates/abis/staking.ts similarity index 100% rename from packages/contracts/e2e/upgrades/exponential-rebates/abis/staking.ts rename to packages/contracts/test/e2e/upgrades/exponential-rebates/abis/staking.ts diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/fixtures/allocations.ts b/packages/contracts/test/e2e/upgrades/exponential-rebates/fixtures/allocations.ts similarity index 100% rename from packages/contracts/e2e/upgrades/exponential-rebates/fixtures/allocations.ts rename to packages/contracts/test/e2e/upgrades/exponential-rebates/fixtures/allocations.ts diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/fixtures/indexers.ts b/packages/contracts/test/e2e/upgrades/exponential-rebates/fixtures/indexers.ts similarity index 100% rename from packages/contracts/e2e/upgrades/exponential-rebates/fixtures/indexers.ts rename to packages/contracts/test/e2e/upgrades/exponential-rebates/fixtures/indexers.ts diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/post-upgrade.test.ts b/packages/contracts/test/e2e/upgrades/exponential-rebates/post-upgrade.test.ts similarity index 86% rename from packages/contracts/e2e/upgrades/exponential-rebates/post-upgrade.test.ts rename to packages/contracts/test/e2e/upgrades/exponential-rebates/post-upgrade.test.ts index 14534f16e..f212343df 100644 --- a/packages/contracts/e2e/upgrades/exponential-rebates/post-upgrade.test.ts +++ b/packages/contracts/test/e2e/upgrades/exponential-rebates/post-upgrade.test.ts @@ -3,7 +3,7 @@ import chaiAsPromised from 'chai-as-promised' import hre from 'hardhat' import { Contract, ethers } from 'ethers' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { helpers, randomHexBytes, AllocationState } from '@graphprotocol/sdk' +import { AllocationState, helpers, randomHexBytes } from '@graphprotocol/sdk' import removedABI from './abis/staking' import allocations from './fixtures/allocations' @@ -32,7 +32,7 @@ describe('[AFTER UPGRADE] Exponential rebates upgrade', () => { describe('> Allocation state transitions', () => { it('Null allocations should remain Null', async function () { - for (const allocation of allocations.filter((a) => a.state === AllocationState.Null)) { + for (const allocation of allocations.filter(a => a.state === AllocationState.Null)) { await expect(Staking.getAllocationState(allocation.id)).to.eventually.equal( AllocationState.Null, ) @@ -40,7 +40,7 @@ describe('[AFTER UPGRADE] Exponential rebates upgrade', () => { }) it('Active allocations should remain Active', async function () { - for (const allocation of allocations.filter((a) => a.state === AllocationState.Active)) { + for (const allocation of allocations.filter(a => a.state === AllocationState.Active)) { await expect(Staking.getAllocationState(allocation.id)).to.eventually.equal( AllocationState.Active, ) @@ -48,7 +48,7 @@ describe('[AFTER UPGRADE] Exponential rebates upgrade', () => { }) it('Closed allocations should remain Closed', async function () { - for (const allocation of allocations.filter((a) => a.state === AllocationState.Closed)) { + for (const allocation of allocations.filter(a => a.state === AllocationState.Closed)) { await expect(Staking.getAllocationState(allocation.id)).to.eventually.equal( AllocationState.Closed, ) @@ -56,7 +56,7 @@ describe('[AFTER UPGRADE] Exponential rebates upgrade', () => { }) it('Finalized allocations should transition to Closed', async function () { - for (const allocation of allocations.filter((a) => a.state === AllocationState.Finalized)) { + for (const allocation of allocations.filter(a => a.state === AllocationState.Finalized)) { await expect(Staking.getAllocationState(allocation.id)).to.eventually.equal( AllocationState.Closed, ) @@ -64,7 +64,7 @@ describe('[AFTER UPGRADE] Exponential rebates upgrade', () => { }) it('Claimed allocations should transition to Closed', async function () { - for (const allocation of allocations.filter((a) => a.state === AllocationState.Claimed)) { + for (const allocation of allocations.filter(a => a.state === AllocationState.Claimed)) { await expect(Staking.getAllocationState(allocation.id)).to.eventually.equal( AllocationState.Closed, ) diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/post-upgrade.ts b/packages/contracts/test/e2e/upgrades/exponential-rebates/post-upgrade.ts similarity index 100% rename from packages/contracts/e2e/upgrades/exponential-rebates/post-upgrade.ts rename to packages/contracts/test/e2e/upgrades/exponential-rebates/post-upgrade.ts diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/pre-upgrade.test.ts b/packages/contracts/test/e2e/upgrades/exponential-rebates/pre-upgrade.test.ts similarity index 100% rename from packages/contracts/e2e/upgrades/exponential-rebates/pre-upgrade.test.ts rename to packages/contracts/test/e2e/upgrades/exponential-rebates/pre-upgrade.test.ts diff --git a/packages/contracts/e2e/upgrades/exponential-rebates/pre-upgrade.ts b/packages/contracts/test/e2e/upgrades/exponential-rebates/pre-upgrade.ts similarity index 95% rename from packages/contracts/e2e/upgrades/exponential-rebates/pre-upgrade.ts rename to packages/contracts/test/e2e/upgrades/exponential-rebates/pre-upgrade.ts index d5e8ffba1..e4bed87b1 100644 --- a/packages/contracts/e2e/upgrades/exponential-rebates/pre-upgrade.ts +++ b/packages/contracts/test/e2e/upgrades/exponential-rebates/pre-upgrade.ts @@ -11,6 +11,7 @@ async function main() { // Make the deployer an asset holder const deployer = await graph.getDeployer() const { governor } = await graph.getNamedAccounts() + // @ts-expect-error asset holder existed back then await Staking.connect(governor).setAssetHolder(deployer.address, true) // Get some funds on the deployer diff --git a/packages/contracts/test/lib/fixtures.ts b/packages/contracts/test/lib/fixtures.ts deleted file mode 100644 index cc851dc32..000000000 --- a/packages/contracts/test/lib/fixtures.ts +++ /dev/null @@ -1,211 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { Signer, providers } from 'ethers' - -import { BridgeMock } from '../../build/types/BridgeMock' -import { InboxMock } from '../../build/types/InboxMock' -import { OutboxMock } from '../../build/types/OutboxMock' -import { Controller } from '../../build/types/Controller' -import { DisputeManager } from '../../build/types/DisputeManager' -import { EpochManager } from '../../build/types/EpochManager' -import { GraphToken } from '../../build/types/GraphToken' -import { Curation } from '../../build/types/Curation' -import { L2Curation } from '../../build/types/L2Curation' -import { L1GNS } from '../../build/types/L1GNS' -import { L2GNS } from '../../build/types/L2GNS' -import { IL1Staking } from '../../build/types/IL1Staking' -import { IL2Staking } from '../../build/types/IL2Staking' -import { RewardsManager } from '../../build/types/RewardsManager' -import { ServiceRegistry } from '../../build/types/ServiceRegistry' -import { GraphProxyAdmin } from '../../build/types/GraphProxyAdmin' -import { L1GraphTokenGateway } from '../../build/types/L1GraphTokenGateway' -import { BridgeEscrow } from '../../build/types/BridgeEscrow' -import { L2GraphTokenGateway } from '../../build/types/L2GraphTokenGateway' -import { L2GraphToken } from '../../build/types/L2GraphToken' -import { LibExponential } from '../../build/types/LibExponential' -import { - DeployType, - GraphNetworkContracts, - deploy, - deployGraphNetwork, - helpers, - loadGraphNetworkContracts, -} from '@graphprotocol/sdk' -import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' - -export interface L1FixtureContracts { - controller: Controller - disputeManager: DisputeManager - epochManager: EpochManager - grt: GraphToken - curation: Curation - gns: L1GNS - staking: IL1Staking - libExponential: LibExponential - rewardsManager: RewardsManager - serviceRegistry: ServiceRegistry - proxyAdmin: GraphProxyAdmin - l1GraphTokenGateway: L1GraphTokenGateway - bridgeEscrow: BridgeEscrow -} - -export interface L2FixtureContracts { - controller: Controller - disputeManager: DisputeManager - epochManager: EpochManager - grt: L2GraphToken - curation: L2Curation - gns: L2GNS - staking: IL2Staking - libExponential: LibExponential - rewardsManager: RewardsManager - serviceRegistry: ServiceRegistry - proxyAdmin: GraphProxyAdmin - l2GraphTokenGateway: L2GraphTokenGateway -} - -export interface ArbitrumL1Mocks { - bridgeMock: BridgeMock - inboxMock: InboxMock - outboxMock: OutboxMock -} - -export class NetworkFixture { - lastSnapshot: any - constructor(public provider: providers.Provider) {} - - async load(deployer: SignerWithAddress, l2Deploy?: boolean): Promise { - // Ensure we are auto mining - await helpers.setIntervalMining(0) - await helpers.setAutoMine(true) - - // Deploy contracts - await deployGraphNetwork( - './addresses-local.json', - l2Deploy ? './config/graph.arbitrum-hardhat.yml' : './config/graph.hardhat.yml', - 1337, - deployer, - this.provider, - { - skipConfirmation: true, - forceDeploy: true, - l2Deploy: l2Deploy, - }, - ) - - const contracts = loadGraphNetworkContracts( - './addresses-local.json', - 1337, - this.provider, - undefined, - { - l2Load: l2Deploy, - }, - ) - - // Post deploy configuration - await contracts.GraphToken.connect(deployer).addMinter(deployer.address) - await contracts.Controller.connect(deployer).setPaused(false) - - return contracts - } - - async loadArbitrumL1Mocks(deployer: Signer): Promise { - const bridgeMock = (await deploy(DeployType.Deploy, deployer, { name: 'BridgeMock' })) - .contract as BridgeMock - const inboxMock = (await deploy(DeployType.Deploy, deployer, { name: 'InboxMock' })) - .contract as InboxMock - const outboxMock = (await deploy(DeployType.Deploy, deployer, { name: 'OutboxMock' })) - .contract as OutboxMock - return { - bridgeMock, - inboxMock, - outboxMock, - } - } - - async configureL1Bridge( - deployer: Signer, - arbitrumMocks: ArbitrumL1Mocks, - l1FixtureContracts: GraphNetworkContracts, - mockRouterAddress: string, - mockL2GRTAddress: string, - mockL2GatewayAddress: string, - mockL2GNSAddress: string, - mockL2StakingAddress: string, - ): Promise { - // First configure the Arbitrum bridge mocks - await arbitrumMocks.bridgeMock.connect(deployer).setInbox(arbitrumMocks.inboxMock.address, true) - await arbitrumMocks.bridgeMock - .connect(deployer) - .setOutbox(arbitrumMocks.outboxMock.address, true) - await arbitrumMocks.inboxMock.connect(deployer).setBridge(arbitrumMocks.bridgeMock.address) - await arbitrumMocks.outboxMock.connect(deployer).setBridge(arbitrumMocks.bridgeMock.address) - - // Configure the gateway - await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).setArbitrumAddresses( - arbitrumMocks.inboxMock.address, - mockRouterAddress, - ) - await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).setL2TokenAddress( - mockL2GRTAddress, - ) - await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).setL2CounterpartAddress( - mockL2GatewayAddress, - ) - await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).setEscrowAddress( - l1FixtureContracts.BridgeEscrow.address, - ) - await l1FixtureContracts.BridgeEscrow.connect(deployer).approveAll( - l1FixtureContracts.L1GraphTokenGateway.address, - ) - await l1FixtureContracts.GNS.connect(deployer).setCounterpartGNSAddress(mockL2GNSAddress) - await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).addToCallhookAllowlist( - l1FixtureContracts.GNS.address, - ) - await l1FixtureContracts.Staking.connect(deployer).setCounterpartStakingAddress( - mockL2StakingAddress, - ) - await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).addToCallhookAllowlist( - l1FixtureContracts.Staking.address, - ) - await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).setPaused(false) - } - - async configureL2Bridge( - deployer: Signer, - l2FixtureContracts: GraphNetworkContracts, - mockRouterAddress: string, - mockL1GRTAddress: string, - mockL1GatewayAddress: string, - mockL1GNSAddress: string, - mockL1StakingAddress: string, - ): Promise { - // Configure the L2 GRT - // Configure the gateway - await l2FixtureContracts.L2GraphToken.connect(deployer).setGateway( - l2FixtureContracts.L2GraphTokenGateway.address, - ) - await l2FixtureContracts.L2GraphToken.connect(deployer).setL1Address(mockL1GRTAddress) - // Configure the gateway - await l2FixtureContracts.L2GraphTokenGateway.connect(deployer).setL2Router(mockRouterAddress) - await l2FixtureContracts.L2GraphTokenGateway.connect(deployer).setL1TokenAddress( - mockL1GRTAddress, - ) - await l2FixtureContracts.L2GraphTokenGateway.connect(deployer).setL1CounterpartAddress( - mockL1GatewayAddress, - ) - await l2FixtureContracts.GNS.connect(deployer).setCounterpartGNSAddress(mockL1GNSAddress) - await l2FixtureContracts.Staking.connect(deployer).setCounterpartStakingAddress( - mockL1StakingAddress, - ) - await l2FixtureContracts.L2GraphTokenGateway.connect(deployer).setPaused(false) - } - - async setUp(): Promise { - this.lastSnapshot = await helpers.takeSnapshot() - } - - async tearDown(): Promise { - await helpers.restoreSnapshot(this.lastSnapshot) - } -} diff --git a/packages/contracts/test/curation/configuration.test.ts b/packages/contracts/test/unit/curation/configuration.test.ts similarity index 99% rename from packages/contracts/test/curation/configuration.test.ts rename to packages/contracts/test/unit/curation/configuration.test.ts index b0346b60b..8e4695234 100644 --- a/packages/contracts/test/curation/configuration.test.ts +++ b/packages/contracts/test/unit/curation/configuration.test.ts @@ -23,7 +23,7 @@ describe('Curation:Config', () => { const defaults = graph.graphConfig.defaults before(async function () { - ;[me] = await graph.getTestAccounts() + [me] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) diff --git a/packages/contracts/test/curation/curation.test.ts b/packages/contracts/test/unit/curation/curation.test.ts similarity index 97% rename from packages/contracts/test/curation/curation.test.ts rename to packages/contracts/test/unit/curation/curation.test.ts index 428b33b86..ee8e30bd7 100644 --- a/packages/contracts/test/curation/curation.test.ts +++ b/packages/contracts/test/unit/curation/curation.test.ts @@ -1,16 +1,16 @@ import hre from 'hardhat' import { expect } from 'chai' -import { utils, BigNumber, Event } from 'ethers' +import { BigNumber, Event, utils } from 'ethers' import { NetworkFixture } from '../lib/fixtures' import { parseEther } from 'ethers/lib/utils' import { formatGRT, + GraphNetworkContracts, + helpers, randomHexBytes, toBN, toGRT, - helpers, - GraphNetworkContracts, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' @@ -29,7 +29,7 @@ const chunkify = (total: BigNumber, maxChunks = 10): Array => { if (total.gt(0)) { chunks.push(total) } - return chunks + return chunks as BigNumber[] } const toFloat = (n: BigNumber) => parseFloat(formatGRT(n)) @@ -60,7 +60,7 @@ describe('Curation', () => { reserveBalance: BigNumber, reserveRatio: number, depositAmount: BigNumber, - ) { + ): Promise { // Handle the initialization of the bonding curve if (supply.eq(0)) { const minDeposit = await contracts.Curation.minimumCurationDeposit() @@ -80,8 +80,8 @@ describe('Curation', () => { } // Calculate bonding curve in the test return ( - toFloat(supply) * - ((1 + toFloat(depositAmount) / toFloat(reserveBalance)) ** (reserveRatio / 1000000) - 1) + toFloat(supply) + * ((1 + toFloat(depositAmount) / toFloat(reserveBalance)) ** (reserveRatio / 1000000) - 1) ) } @@ -201,7 +201,7 @@ describe('Curation', () => { before(async function () { // Use stakingMock so we can call collect - ;[me, curator, stakingMock] = await graph.getTestAccounts() + [me, curator, stakingMock] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) @@ -288,7 +288,7 @@ describe('Curation', () => { }) }) - describe('curate', async function () { + describe('curate', function () { it('reject deposit below minimum tokens required', async function () { const tokensToDeposit = (await contracts.Curation.minimumCurationDeposit()).sub(toBN(1)) const tx = contracts.Curation.connect(curator).mint(subgraphDeploymentID, tokensToDeposit, 0) @@ -332,8 +332,8 @@ describe('Curation', () => { }) }) - describe('collect', async function () { - context('> not curated', async function () { + describe('collect', function () { + context('> not curated', function () { it('reject collect tokens distributed to the curation pool', async function () { // Source of tokens must be the staking for this to work await contracts.Controller.connect(governor).setContractProxy( @@ -350,7 +350,7 @@ describe('Curation', () => { }) }) - context('> curated', async function () { + context('> curated', function () { beforeEach(async function () { await contracts.Curation.connect(curator).mint(subgraphDeploymentID, toGRT('1000'), 0) }) @@ -435,7 +435,7 @@ describe('Curation', () => { }) }) - describe('burn', async function () { + describe('burn', function () { beforeEach(async function () { await contracts.Curation.connect(curator).mint(subgraphDeploymentID, tokensToDeposit, 0) }) @@ -528,7 +528,7 @@ describe('Curation', () => { }) }) - describe('conservation', async function () { + describe('conservation', function () { it('should match multiple deposits and redeems back to initial state', async function () { this.timeout(60000) // increase timeout for test runner @@ -573,7 +573,7 @@ describe('Curation', () => { }) }) - describe('multiple minting', async function () { + describe('multiple minting', function () { it('should mint less signal every time due to the bonding curve', async function () { const tokensToDepositMany = [ toGRT('1000'), // should mint if we start with number above minimum deposit diff --git a/packages/contracts/test/disputes/common.ts b/packages/contracts/test/unit/disputes/common.ts similarity index 100% rename from packages/contracts/test/disputes/common.ts rename to packages/contracts/test/unit/disputes/common.ts diff --git a/packages/contracts/test/disputes/configuration.test.ts b/packages/contracts/test/unit/disputes/configuration.test.ts similarity index 95% rename from packages/contracts/test/disputes/configuration.test.ts rename to packages/contracts/test/unit/disputes/configuration.test.ts index 259f9508f..baf426815 100644 --- a/packages/contracts/test/disputes/configuration.test.ts +++ b/packages/contracts/test/unit/disputes/configuration.test.ts @@ -2,7 +2,7 @@ import hre from 'hardhat' import { constants } from 'ethers' import { expect } from 'chai' -import { DisputeManager } from '../../build/types/DisputeManager' +import { DisputeManager } from '../../../build/types/DisputeManager' import { NetworkFixture } from '../lib/fixtures' import { GraphNetworkContracts, toBN } from '@graphprotocol/sdk' @@ -15,7 +15,6 @@ const MAX_PPM = 1000000 describe('DisputeManager:Config', () => { let me: SignerWithAddress let governor: SignerWithAddress - let slasher: SignerWithAddress let arbitrator: SignerWithAddress const graph = hre.graph() @@ -26,12 +25,12 @@ describe('DisputeManager:Config', () => { let disputeManager: DisputeManager before(async function () { - ;[me, slasher] = await graph.getTestAccounts() + [me] = await graph.getTestAccounts() ;({ governor, arbitrator } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) - disputeManager = contracts.DisputeManager as DisputeManager + disputeManager = contracts.DisputeManager }) beforeEach(async function () { diff --git a/packages/contracts/test/disputes/poi.test.ts b/packages/contracts/test/unit/disputes/poi.test.ts similarity index 94% rename from packages/contracts/test/disputes/poi.test.ts rename to packages/contracts/test/unit/disputes/poi.test.ts index 2a311be27..ea644c522 100644 --- a/packages/contracts/test/disputes/poi.test.ts +++ b/packages/contracts/test/unit/disputes/poi.test.ts @@ -2,28 +2,27 @@ import hre from 'hardhat' import { expect } from 'chai' import { utils } from 'ethers' -import { DisputeManager } from '../../build/types/DisputeManager' -import { EpochManager } from '../../build/types/EpochManager' -import { GraphToken } from '../../build/types/GraphToken' -import { IStaking } from '../../build/types/IStaking' +import { DisputeManager } from '../../../build/types/DisputeManager' +import { EpochManager } from '../../../build/types/EpochManager' +import { GraphToken } from '../../../build/types/GraphToken' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' import { MAX_PPM } from './common' import { - helpers, deriveChannelKey, + GraphNetworkContracts, + helpers, randomHexBytes, toBN, toGRT, - GraphNetworkContracts, } from '@graphprotocol/sdk' import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' const { keccak256 } = utils -describe('DisputeManager:POI', async () => { - let other: SignerWithAddress +describe('DisputeManager:POI', () => { let governor: SignerWithAddress let arbitrator: SignerWithAddress let indexer: SignerWithAddress @@ -95,13 +94,13 @@ describe('DisputeManager:POI', async () => { } before(async function () { - ;[other, indexer, fisherman, assetHolder, rewardsDestination] = await graph.getTestAccounts() + [indexer, fisherman, assetHolder, rewardsDestination] = await graph.getTestAccounts() ;({ governor, arbitrator } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) - disputeManager = contracts.DisputeManager as DisputeManager - epochManager = contracts.EpochManager as EpochManager + disputeManager = contracts.DisputeManager + epochManager = contracts.EpochManager grt = contracts.GraphToken as GraphToken staking = contracts.Staking as IStaking diff --git a/packages/contracts/test/disputes/query.test.ts b/packages/contracts/test/unit/disputes/query.test.ts similarity index 96% rename from packages/contracts/test/disputes/query.test.ts rename to packages/contracts/test/unit/disputes/query.test.ts index e00db65b6..38b8c04a2 100644 --- a/packages/contracts/test/disputes/query.test.ts +++ b/packages/contracts/test/unit/disputes/query.test.ts @@ -3,32 +3,31 @@ import { expect } from 'chai' import { constants } from 'ethers' import { createAttestation, Receipt } from '@graphprotocol/common-ts' -import { DisputeManager } from '../../build/types/DisputeManager' -import { EpochManager } from '../../build/types/EpochManager' -import { GraphToken } from '../../build/types/GraphToken' -import { IStaking } from '../../build/types/IStaking' +import { DisputeManager } from '../../../build/types/DisputeManager' +import { EpochManager } from '../../../build/types/EpochManager' +import { GraphToken } from '../../../build/types/GraphToken' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' -import { Dispute, createQueryDisputeID, encodeAttestation, MAX_PPM } from './common' +import { createQueryDisputeID, Dispute, encodeAttestation, MAX_PPM } from './common' import { - helpers, deriveChannelKey, + GraphNetworkContracts, + helpers, randomHexBytes, toBN, toGRT, - GraphNetworkContracts, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -const { AddressZero, HashZero } = constants +const { HashZero } = constants const NON_EXISTING_DISPUTE_ID = randomHexBytes() -describe('DisputeManager:Query', async () => { +describe('DisputeManager:Query', () => { let me: SignerWithAddress - let other: SignerWithAddress let governor: SignerWithAddress let arbitrator: SignerWithAddress let indexer: SignerWithAddress @@ -129,14 +128,14 @@ describe('DisputeManager:Query', async () => { } before(async function () { - ;[me, other, indexer, indexer2, fisherman, fisherman2, assetHolder, rewardsDestination] = - await graph.getTestAccounts() + [me, indexer, indexer2, fisherman, fisherman2, assetHolder, rewardsDestination] + = await graph.getTestAccounts() ;({ governor, arbitrator } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) - disputeManager = contracts.DisputeManager as DisputeManager - epochManager = contracts.EpochManager as EpochManager + disputeManager = contracts.DisputeManager + epochManager = contracts.EpochManager grt = contracts.GraphToken as GraphToken staking = contracts.Staking as IStaking @@ -388,7 +387,7 @@ describe('DisputeManager:Query', async () => { }) }) - describe('reject a dispute', async function () { + describe('reject a dispute', function () { it('reject to reject a dispute if not the arbitrator', async function () { const tx = disputeManager.connect(me).rejectDispute(dispute.id) await expect(tx).revertedWith('Caller is not the Arbitrator') @@ -417,7 +416,7 @@ describe('DisputeManager:Query', async () => { }) }) - describe('draw a dispute', async function () { + describe('draw a dispute', function () { it('reject to draw a dispute if not the arbitrator', async function () { const tx = disputeManager.connect(me).drawDispute(dispute.id) await expect(tx).revertedWith('Caller is not the Arbitrator') diff --git a/packages/contracts/test/epochs.test.ts b/packages/contracts/test/unit/epochs.test.ts similarity index 96% rename from packages/contracts/test/epochs.test.ts rename to packages/contracts/test/unit/epochs.test.ts index 70a9c494a..951114dfd 100644 --- a/packages/contracts/test/epochs.test.ts +++ b/packages/contracts/test/unit/epochs.test.ts @@ -2,9 +2,9 @@ import hre from 'hardhat' import { expect } from 'chai' import { BigNumber } from 'ethers' -import { EpochManager } from '../build/types/EpochManager' +import { EpochManager } from '../../build/types/EpochManager' -import { DeployType, deploy, helpers, toBN } from '@graphprotocol/sdk' +import { deploy, DeployType, helpers, toBN } from '@graphprotocol/sdk' import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' describe('EpochManager', () => { @@ -18,7 +18,7 @@ describe('EpochManager', () => { const epochLength: BigNumber = toBN('3') before(async function () { - ;[me, governor] = await graph.getTestAccounts() + [me, governor] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) }) @@ -31,7 +31,7 @@ describe('EpochManager', () => { }, graph.addressBook, ) - const { contract: proxyAdmin } = await deploy( + await deploy( DeployType.DeployAndSave, governor, { diff --git a/packages/contracts/test/gateway/bridgeEscrow.test.ts b/packages/contracts/test/unit/gateway/bridgeEscrow.test.ts similarity index 88% rename from packages/contracts/test/gateway/bridgeEscrow.test.ts rename to packages/contracts/test/unit/gateway/bridgeEscrow.test.ts index 2af2d1760..34fa860fd 100644 --- a/packages/contracts/test/gateway/bridgeEscrow.test.ts +++ b/packages/contracts/test/unit/gateway/bridgeEscrow.test.ts @@ -2,8 +2,8 @@ import hre from 'hardhat' import { expect } from 'chai' import { BigNumber } from 'ethers' -import { GraphToken } from '../../build/types/GraphToken' -import { BridgeEscrow } from '../../build/types/BridgeEscrow' +import { GraphToken } from '../../../build/types/GraphToken' +import { BridgeEscrow } from '../../../build/types/BridgeEscrow' import { NetworkFixture } from '../lib/fixtures' @@ -25,13 +25,13 @@ describe('BridgeEscrow', () => { const nTokens = toGRT('1000') before(async function () { - ;[tokenReceiver, spender] = await graph.getTestAccounts() + [tokenReceiver, spender] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) grt = contracts.GraphToken as GraphToken - bridgeEscrow = contracts.BridgeEscrow as BridgeEscrow + bridgeEscrow = contracts.BridgeEscrow // Give some funds to the Escrow await grt.connect(governor).mint(bridgeEscrow.address, nTokens) @@ -69,7 +69,7 @@ describe('BridgeEscrow', () => { const tx = bridgeEscrow.connect(tokenReceiver).revokeAll(spender.address) await expect(tx).revertedWith('Only Controller governor') }) - it("revokes a spender's permission to transfer GRT held by the contract", async function () { + it('revokes a spender\'s permission to transfer GRT held by the contract', async function () { await bridgeEscrow.connect(governor).approveAll(spender.address) await bridgeEscrow.connect(governor).revokeAll(spender.address) // We shouldn't be able to transfer _anything_ diff --git a/packages/contracts/test/gateway/l1GraphTokenGateway.test.ts b/packages/contracts/test/unit/gateway/l1GraphTokenGateway.test.ts similarity index 90% rename from packages/contracts/test/gateway/l1GraphTokenGateway.test.ts rename to packages/contracts/test/unit/gateway/l1GraphTokenGateway.test.ts index 93067fcfd..872ff77fe 100644 --- a/packages/contracts/test/gateway/l1GraphTokenGateway.test.ts +++ b/packages/contracts/test/unit/gateway/l1GraphTokenGateway.test.ts @@ -1,17 +1,18 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants, Signer, utils } from 'ethers' +import { constants, Signer, utils, Wallet } from 'ethers' -import { GraphToken } from '../../build/types/GraphToken' -import { BridgeMock } from '../../build/types/BridgeMock' -import { InboxMock } from '../../build/types/InboxMock' -import { OutboxMock } from '../../build/types/OutboxMock' -import { L1GraphTokenGateway } from '../../build/types/L1GraphTokenGateway' +import { GraphToken } from '../../../build/types/GraphToken' +import { BridgeMock } from '../../../build/types/BridgeMock' +import { InboxMock } from '../../../build/types/InboxMock' +import { OutboxMock } from '../../../build/types/OutboxMock' +import { L1GraphTokenGateway } from '../../../build/types/L1GraphTokenGateway' +import { L2GraphToken, L2GraphTokenGateway } from '../../../build/types' +import { BridgeEscrow } from '../../../build/types/BridgeEscrow' -import { NetworkFixture, ArbitrumL1Mocks, L1FixtureContracts } from '../lib/fixtures' +import { NetworkFixture } from '../lib/fixtures' -import { BridgeEscrow } from '../../build/types/BridgeEscrow' -import { helpers, applyL1ToL2Alias, toBN, toGRT, GraphNetworkContracts } from '@graphprotocol/sdk' +import { applyL1ToL2Alias, GraphNetworkContracts, helpers, toBN, toGRT } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' const { AddressZero } = constants @@ -21,23 +22,22 @@ describe('L1GraphTokenGateway', () => { let governor: SignerWithAddress let tokenSender: SignerWithAddress let l2Receiver: SignerWithAddress - let mockRouter: SignerWithAddress - let mockL2GRT: SignerWithAddress - let mockL2Gateway: SignerWithAddress let pauseGuardian: SignerWithAddress - let mockL2GNS: SignerWithAddress - let mockL2Staking: SignerWithAddress - let fixture: NetworkFixture + let fixture: NetworkFixture let grt: GraphToken let l1GraphTokenGateway: L1GraphTokenGateway let bridgeEscrow: BridgeEscrow + let bridgeMock: BridgeMock let inboxMock: InboxMock let outboxMock: OutboxMock + let routerMock: Wallet + let l2GRTMock: L2GraphToken + let l2GRTGatewayMock: L2GraphTokenGateway - let arbitrumMocks: ArbitrumL1Mocks let fixtureContracts: GraphNetworkContracts + let l2MockContracts: GraphNetworkContracts const senderTokens = toGRT('1000') const maxGas = toBN('1000000') @@ -60,23 +60,30 @@ describe('L1GraphTokenGateway', () => { ) before(async function () { - ;[tokenSender, l2Receiver, mockRouter, mockL2GRT, mockL2Gateway, mockL2GNS, mockL2Staking] = - await graph.getTestAccounts() + [tokenSender, l2Receiver] = await graph.getTestAccounts() ;({ governor, pauseGuardian } = await graph.getNamedAccounts()) - // Dummy code on the mock router so that it appears as a contract - await helpers.setCode(mockRouter.address, '0x1234') fixture = new NetworkFixture(graph.provider) + + // Deploy L1 fixtureContracts = await fixture.load(governor) grt = fixtureContracts.GraphToken as GraphToken - l1GraphTokenGateway = fixtureContracts.L1GraphTokenGateway as L1GraphTokenGateway - bridgeEscrow = fixtureContracts.BridgeEscrow as BridgeEscrow + l1GraphTokenGateway = fixtureContracts.L1GraphTokenGateway + bridgeEscrow = fixtureContracts.BridgeEscrow + + // Deploy L1 arbitrum bridge + ;({ bridgeMock, inboxMock, outboxMock, routerMock } = await fixture.loadL1ArbitrumBridge( + governor, + )) + + // Deploy L2 mock + l2MockContracts = await fixture.loadMock(true) + l2GRTMock = l2MockContracts.L2GraphToken + l2GRTGatewayMock = l2MockContracts.L2GraphTokenGateway - // Give some funds to the token sender + // Give some funds to the token sender/router mock await grt.connect(governor).mint(tokenSender.address, senderTokens) - // Deploy contracts that mock Arbitrum's bridge contracts - arbitrumMocks = await fixture.loadArbitrumL1Mocks(governor) - ;({ bridgeMock, inboxMock, outboxMock } = arbitrumMocks) + await helpers.setBalance(routerMock.address, utils.parseEther('1')) }) beforeEach(async function () { @@ -132,13 +139,13 @@ describe('L1GraphTokenGateway', () => { it('is not callable by addreses that are not the governor', async function () { const tx = l1GraphTokenGateway .connect(tokenSender) - .setArbitrumAddresses(inboxMock.address, mockRouter.address) + .setArbitrumAddresses(inboxMock.address, routerMock.address) await expect(tx).revertedWith('Only Controller governor') }) it('rejects setting an EOA as router or inbox', async function () { let tx = l1GraphTokenGateway .connect(governor) - .setArbitrumAddresses(tokenSender.address, mockRouter.address) + .setArbitrumAddresses(tokenSender.address, routerMock.address) await expect(tx).revertedWith('INBOX_MUST_BE_CONTRACT') tx = l1GraphTokenGateway .connect(governor) @@ -148,24 +155,24 @@ describe('L1GraphTokenGateway', () => { it('sets inbox and router address', async function () { const tx = l1GraphTokenGateway .connect(governor) - .setArbitrumAddresses(inboxMock.address, mockRouter.address) + .setArbitrumAddresses(inboxMock.address, routerMock.address) await expect(tx) .emit(l1GraphTokenGateway, 'ArbitrumAddressesSet') - .withArgs(inboxMock.address, mockRouter.address) - expect(await l1GraphTokenGateway.l1Router()).eq(mockRouter.address) + .withArgs(inboxMock.address, routerMock.address) + expect(await l1GraphTokenGateway.l1Router()).eq(routerMock.address) expect(await l1GraphTokenGateway.inbox()).eq(inboxMock.address) }) }) describe('setL2TokenAddress', function () { it('is not callable by addreses that are not the governor', async function () { - const tx = l1GraphTokenGateway.connect(tokenSender).setL2TokenAddress(mockL2GRT.address) + const tx = l1GraphTokenGateway.connect(tokenSender).setL2TokenAddress(l2GRTMock.address) await expect(tx).revertedWith('Only Controller governor') }) it('sets l2GRT', async function () { - const tx = l1GraphTokenGateway.connect(governor).setL2TokenAddress(mockL2GRT.address) - await expect(tx).emit(l1GraphTokenGateway, 'L2TokenAddressSet').withArgs(mockL2GRT.address) - expect(await l1GraphTokenGateway.l2GRT()).eq(mockL2GRT.address) + const tx = l1GraphTokenGateway.connect(governor).setL2TokenAddress(l2GRTMock.address) + await expect(tx).emit(l1GraphTokenGateway, 'L2TokenAddressSet').withArgs(l2GRTMock.address) + expect(await l1GraphTokenGateway.l2GRT()).eq(l2GRTMock.address) }) }) @@ -173,18 +180,18 @@ describe('L1GraphTokenGateway', () => { it('is not callable by addreses that are not the governor', async function () { const tx = l1GraphTokenGateway .connect(tokenSender) - .setL2CounterpartAddress(mockL2Gateway.address) + .setL2CounterpartAddress(l2GRTGatewayMock.address) await expect(tx).revertedWith('Only Controller governor') }) it('sets l2Counterpart which can be queried with counterpartGateway()', async function () { const tx = l1GraphTokenGateway .connect(governor) - .setL2CounterpartAddress(mockL2Gateway.address) + .setL2CounterpartAddress(l2GRTGatewayMock.address) await expect(tx) .emit(l1GraphTokenGateway, 'L2CounterpartAddressSet') - .withArgs(mockL2Gateway.address) - expect(await l1GraphTokenGateway.l2Counterpart()).eq(mockL2Gateway.address) - expect(await l1GraphTokenGateway.counterpartGateway()).eq(mockL2Gateway.address) + .withArgs(l2GRTGatewayMock.address) + expect(await l1GraphTokenGateway.l2Counterpart()).eq(l2GRTGatewayMock.address) + expect(await l1GraphTokenGateway.counterpartGateway()).eq(l2GRTGatewayMock.address) }) }) describe('setEscrowAddress', function () { @@ -266,30 +273,23 @@ describe('L1GraphTokenGateway', () => { await expect(tx).revertedWith('INBOX_NOT_SET') await l1GraphTokenGateway .connect(governor) - .setArbitrumAddresses(arbitrumMocks.inboxMock.address, mockRouter.address) + .setArbitrumAddresses(inboxMock.address, routerMock.address) tx = l1GraphTokenGateway.connect(governor).setPaused(false) await expect(tx).revertedWith('L2_COUNTERPART_NOT_SET') - await l1GraphTokenGateway.connect(governor).setL2CounterpartAddress(mockL2Gateway.address) + await l1GraphTokenGateway + .connect(governor) + .setL2CounterpartAddress(l2GRTGatewayMock.address) tx = l1GraphTokenGateway.connect(governor).setPaused(false) await expect(tx).revertedWith('ESCROW_NOT_SET') }) it('can be paused and unpaused by the governor', async function () { - await fixture.configureL1Bridge( - governor, - arbitrumMocks, - fixtureContracts, - mockRouter.address, - mockL2GRT.address, - mockL2Gateway.address, - mockL2GNS.address, - mockL2Staking.address, - ) + await fixture.configureL1Bridge(governor, fixtureContracts, l2MockContracts) let tx = l1GraphTokenGateway.connect(governor).setPaused(true) await expect(tx).emit(l1GraphTokenGateway, 'PauseChanged').withArgs(true) - await expect(await l1GraphTokenGateway.paused()).eq(true) + expect(await l1GraphTokenGateway.paused()).eq(true) tx = l1GraphTokenGateway.connect(governor).setPaused(false) await expect(tx).emit(l1GraphTokenGateway, 'PauseChanged').withArgs(false) - await expect(await l1GraphTokenGateway.paused()).eq(false) + expect(await l1GraphTokenGateway.paused()).eq(false) }) describe('setPauseGuardian', function () { it('cannot be called by someone other than governor', async function () { @@ -306,23 +306,14 @@ describe('L1GraphTokenGateway', () => { .withArgs(currentPauseGuardian, pauseGuardian.address) }) it('allows a pause guardian to pause and unpause', async function () { - await fixture.configureL1Bridge( - governor, - arbitrumMocks, - fixtureContracts, - mockRouter.address, - mockL2GRT.address, - mockL2Gateway.address, - mockL2GNS.address, - mockL2Staking.address, - ) + await fixture.configureL1Bridge(governor, fixtureContracts, l2MockContracts) await l1GraphTokenGateway.connect(governor).setPauseGuardian(pauseGuardian.address) let tx = l1GraphTokenGateway.connect(pauseGuardian).setPaused(true) await expect(tx).emit(l1GraphTokenGateway, 'PauseChanged').withArgs(true) - await expect(await l1GraphTokenGateway.paused()).eq(true) + expect(await l1GraphTokenGateway.paused()).eq(true) tx = l1GraphTokenGateway.connect(pauseGuardian).setPaused(false) await expect(tx).emit(l1GraphTokenGateway, 'PauseChanged').withArgs(false) - await expect(await l1GraphTokenGateway.paused()).eq(false) + expect(await l1GraphTokenGateway.paused()).eq(false) }) }) }) @@ -351,7 +342,7 @@ describe('L1GraphTokenGateway', () => { 'bytes', ], [ - toBN(mockL2Gateway.address), + toBN(l2GRTGatewayMock.address), toBN('0'), defaultEthValue, maxSubmissionCost, @@ -413,16 +404,7 @@ describe('L1GraphTokenGateway', () => { expect(senderBalance).eq(toGRT('990')) } before(async function () { - await fixture.configureL1Bridge( - governor, - arbitrumMocks, - fixtureContracts, - mockRouter.address, - mockL2GRT.address, - mockL2Gateway.address, - mockL2GNS.address, - mockL2Staking.address, - ) + await fixture.configureL1Bridge(governor, fixtureContracts, l2MockContracts) }) describe('updateL2MintAllowance', function () { @@ -604,7 +586,7 @@ describe('L1GraphTokenGateway', () => { }) describe('calculateL2TokenAddress', function () { it('returns the L2 token address', async function () { - expect(await l1GraphTokenGateway.calculateL2TokenAddress(grt.address)).eq(mockL2GRT.address) + expect(await l1GraphTokenGateway.calculateL2TokenAddress(grt.address)).eq(l2GRTMock.address) }) it('returns the zero address if the input is any other address', async function () { expect(await l1GraphTokenGateway.calculateL2TokenAddress(tokenSender.address)).eq( @@ -640,7 +622,7 @@ describe('L1GraphTokenGateway', () => { ['address', 'bytes'], [tokenSender.address, defaultData], ) - await testValidOutboundTransfer(mockRouter, routerEncodedData, emptyCallHookData) + await testValidOutboundTransfer(routerMock, routerEncodedData, emptyCallHookData) }) it('reverts when called with no submission cost', async function () { await grt.connect(tokenSender).approve(l1GraphTokenGateway.address, toGRT('10')) @@ -737,7 +719,7 @@ describe('L1GraphTokenGateway', () => { toBN('0'), [], toBN('0'), - l2Receiver.address, // Note this is not mockL2Gateway + l2Receiver.address, // Note this is not l2GRTGatewayMock l1GraphTokenGateway.address, toBN('1337'), await helpers.latestBlock(), @@ -769,7 +751,7 @@ describe('L1GraphTokenGateway', () => { toBN('0'), [], toBN('0'), - mockL2Gateway.address, + l2GRTGatewayMock.address, l1GraphTokenGateway.address, toBN('1337'), await helpers.latestBlock(), @@ -804,7 +786,7 @@ describe('L1GraphTokenGateway', () => { toBN('0'), [], toBN('0'), - mockL2Gateway.address, + l2GRTGatewayMock.address, l1GraphTokenGateway.address, toBN('1337'), await helpers.latestBlock(), @@ -837,7 +819,7 @@ describe('L1GraphTokenGateway', () => { toBN('0'), [], toBN('0'), - mockL2Gateway.address, + l2GRTGatewayMock.address, l1GraphTokenGateway.address, toBN('1337'), await helpers.latestBlock(), @@ -885,7 +867,7 @@ describe('L1GraphTokenGateway', () => { toBN('0'), [], toBN('0'), - mockL2Gateway.address, + l2GRTGatewayMock.address, l1GraphTokenGateway.address, toBN('1337'), await helpers.latestBlock(), @@ -940,7 +922,7 @@ describe('L1GraphTokenGateway', () => { toBN('0'), [], toBN('0'), - mockL2Gateway.address, + l2GRTGatewayMock.address, l1GraphTokenGateway.address, toBN('1337'), await helpers.latestBlock(), diff --git a/packages/contracts/test/gns.test.ts b/packages/contracts/test/unit/gns.test.ts similarity index 95% rename from packages/contracts/test/gns.test.ts rename to packages/contracts/test/unit/gns.test.ts index f73c3e8ea..028d6b729 100644 --- a/packages/contracts/test/gns.test.ts +++ b/packages/contracts/test/unit/gns.test.ts @@ -1,43 +1,43 @@ import hre from 'hardhat' import { expect } from 'chai' -import { ethers, ContractTransaction, BigNumber, Event } from 'ethers' +import { BigNumber, ContractTransaction, ethers, Event } from 'ethers' import { defaultAbiCoder } from 'ethers/lib/utils' -import { SubgraphDeploymentID, formatGRT } from '@graphprotocol/common-ts' +import { formatGRT, SubgraphDeploymentID } from '@graphprotocol/common-ts' -import { LegacyGNSMock } from '../build/types/LegacyGNSMock' -import { GraphToken } from '../build/types/GraphToken' -import { Curation } from '../build/types/Curation' +import { LegacyGNSMock } from '../../build/types/LegacyGNSMock' +import { GraphToken } from '../../build/types/GraphToken' +import { Curation } from '../../build/types/Curation' -import { ArbitrumL1Mocks, NetworkFixture } from './lib/fixtures' -import { Controller } from '../build/types/Controller' -import { GraphProxyAdmin } from '../build/types/GraphProxyAdmin' -import { L1GNS } from '../build/types/L1GNS' -import { L1GraphTokenGateway } from '../build/types/L1GraphTokenGateway' +import { NetworkFixture } from './lib/fixtures' +import { Controller } from '../../build/types/Controller' +import { L1GNS } from '../../build/types/L1GNS' +import { L1GraphTokenGateway } from '../../build/types/L1GraphTokenGateway' import { AccountDefaultName, + burnSignal, createDefaultName, + deprecateSubgraph, + mintSignal, publishNewSubgraph, publishNewVersion, - mintSignal, - deprecateSubgraph, - burnSignal, } from './lib/gnsUtils' import { - PublishSubgraph, - Subgraph, buildLegacySubgraphId, buildSubgraph, buildSubgraphId, - randomHexBytes, - helpers, - toGRT, - toBN, deploy, DeployType, + GraphNetworkContracts, + helpers, loadContractAt, + PublishSubgraph, + randomHexBytes, + Subgraph, + toBN, + toGRT, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { SubgraphNFT } from '../build/types' +import { L2GNS, L2GraphTokenGateway, SubgraphNFT } from '../../build/types' const { AddressZero, HashZero } = ethers.constants @@ -52,23 +52,20 @@ describe('L1GNS', () => { let other: SignerWithAddress let another: SignerWithAddress let governor: SignerWithAddress - let mockRouter: SignerWithAddress - let mockL2GRT: SignerWithAddress - let mockL2Gateway: SignerWithAddress - let mockL2GNS: SignerWithAddress - let mockL2Staking: SignerWithAddress let fixture: NetworkFixture + let l2MockContracts: GraphNetworkContracts + + let l2GNSMock: L2GNS + let l2GRTGatewayMock: L2GraphTokenGateway let gns: L1GNS let legacyGNSMock: LegacyGNSMock let grt: GraphToken let curation: Curation let controller: Controller - let proxyAdmin: GraphProxyAdmin let subgraphNFT: SubgraphNFT let l1GraphTokenGateway: L1GraphTokenGateway - let arbitrumMocks: ArbitrumL1Mocks const tokens1000 = toGRT('1000') const tokens10000 = toGRT('10000') @@ -128,8 +125,8 @@ describe('L1GNS', () => { } // Calculate bonding curve in the test return ( - toFloat(supply) * - ((1 + toFloat(depositAmount) / toFloat(reserveBalance)) ** (reserveRatio / 1000000) - 1) + toFloat(supply) + * ((1 + toFloat(depositAmount) / toFloat(reserveBalance)) ** (reserveRatio / 1000000) - 1) ) } @@ -193,8 +190,7 @@ describe('L1GNS', () => { return tx } - - const deployLegacyGNSMock = async (): Promise => { + const deployLegacyGNSMock = async (): Promise => { const { contract: subgraphDescriptor } = await deploy(DeployType.Deploy, governor, { name: 'SubgraphNFTDescriptor', }) @@ -221,32 +217,33 @@ describe('L1GNS', () => { await legacyGNSMock.connect(governor).syncAllContracts() await legacyGNSMock.connect(governor).approveAll() await l1GraphTokenGateway.connect(governor).addToCallhookAllowlist(legacyGNSMock.address) - await legacyGNSMock.connect(governor).setCounterpartGNSAddress(mockL2GNS.address) + await legacyGNSMock.connect(governor).setCounterpartGNSAddress(l2GNSMock.address) } before(async function () { - ;[ - me, - other, - governor, - another, - mockRouter, - mockL2GRT, - mockL2Gateway, - mockL2GNS, - mockL2Staking, - ] = await graph.getTestAccounts() - // Dummy code on the mock router so that it appears as a contract - await helpers.setCode(mockRouter.address, '0x1234') + [me, other, governor, another] = await graph.getTestAccounts() + fixture = new NetworkFixture(graph.provider) + + // Deploy L1 const fixtureContracts = await fixture.load(governor) grt = fixtureContracts.GraphToken as GraphToken curation = fixtureContracts.Curation as Curation gns = fixtureContracts.GNS as L1GNS - controller = fixtureContracts.Controller as Controller - proxyAdmin = fixtureContracts.GraphProxyAdmin as GraphProxyAdmin - l1GraphTokenGateway = fixtureContracts.L1GraphTokenGateway as L1GraphTokenGateway - subgraphNFT = fixtureContracts.SubgraphNFT as SubgraphNFT + controller = fixtureContracts.Controller + l1GraphTokenGateway = fixtureContracts.L1GraphTokenGateway + subgraphNFT = fixtureContracts.SubgraphNFT + + // Deploy L1 arbitrum bridge + await fixture.loadL1ArbitrumBridge(governor) + + // Deploy L2 mock + l2MockContracts = await fixture.loadMock(true) + l2GNSMock = l2MockContracts.L2GNS + l2GRTGatewayMock = l2MockContracts.L2GraphTokenGateway + + // Configure graph bridge + await fixture.configureL1Bridge(governor, fixtureContracts, l2MockContracts) newSubgraph0 = buildSubgraph() newSubgraph1 = buildSubgraph() @@ -267,18 +264,6 @@ describe('L1GNS', () => { // Deploying a GNS mock with support for legacy subgraphs await deployLegacyGNSMock() await grt.connect(me).approve(legacyGNSMock.address, tokens100000) - - arbitrumMocks = await fixture.loadArbitrumL1Mocks(governor) - await fixture.configureL1Bridge( - governor, - arbitrumMocks, - fixtureContracts, - mockRouter.address, - mockL2GRT.address, - mockL2Gateway.address, - mockL2GNS.address, - mockL2Staking.address, - ) }) beforeEach(async function () { @@ -289,7 +274,7 @@ describe('L1GNS', () => { await fixture.tearDown() }) - describe('Configuration', async function () { + describe('Configuration', function () { describe('setOwnerTaxPercentage', function () { const newValue = 10 @@ -398,7 +383,7 @@ describe('L1GNS', () => { }) }) - describe('publishNewSubgraph', async function () { + describe('publishNewSubgraph', function () { it('should publish a new subgraph and first version with it', async function () { await publishNewSubgraph(me, newSubgraph0, gns, graph.chainId) }) @@ -417,7 +402,7 @@ describe('L1GNS', () => { }) }) - describe('publishNewVersion', async function () { + describe('publishNewVersion', function () { let subgraph: Subgraph beforeEach(async () => { @@ -434,6 +419,11 @@ describe('L1GNS', () => { await publishNewVersion(me, subgraph.id, newSubgraph1, gns, curation) }) + it('should publish a new version on an existing subgraph when curation tax percentage is zero', async function () { + await curation.connect(governor).setCurationTaxPercentage(0) + await publishNewVersion(me, subgraph.id, newSubgraph1, gns, curation) + }) + it('should publish a new version on an existing subgraph with no current signal', async function () { const emptySignalSubgraph = await publishNewSubgraph( me, @@ -557,7 +547,7 @@ describe('L1GNS', () => { expect(await gns.subgraphSignal(subgraph.id)).eq(expectedSignal) }) }) - describe('deprecateSubgraph', async function () { + describe('deprecateSubgraph', function () { let subgraph: Subgraph beforeEach(async () => { @@ -595,8 +585,8 @@ describe('L1GNS', () => { }) }) - describe('Curating on names', async function () { - describe('mintSignal()', async function () { + describe('Curating on names', function () { + describe('mintSignal()', function () { it('should deposit into the name signal curve', async function () { const subgraph = await publishNewSubgraph(me, newSubgraph0, gns, graph.chainId) await mintSignal(other, subgraph.id, tokens10000, gns, curation) @@ -626,7 +616,7 @@ describe('L1GNS', () => { }) }) - describe('burnSignal()', async function () { + describe('burnSignal()', function () { let subgraph: Subgraph beforeEach(async () => { @@ -668,7 +658,7 @@ describe('L1GNS', () => { }) }) - describe('transferSignal()', async function () { + describe('transferSignal()', function () { let subgraph: Subgraph let otherNSignal: BigNumber @@ -681,7 +671,7 @@ describe('L1GNS', () => { it('should transfer signal from one curator to another', async function () { await transferSignal(subgraph.id, other, another, otherNSignal) }) - it('should fail when transfering to zero address', async function () { + it('should fail when transferring to zero address', async function () { const tx = gns .connect(other) .transferSignal(subgraph.id, ethers.constants.AddressZero, otherNSignal) @@ -704,7 +694,7 @@ describe('L1GNS', () => { await expect(tx).revertedWith('GNS: Curator transfer amount exceeds balance') }) }) - describe('withdraw()', async function () { + describe('withdraw()', function () { let subgraph: Subgraph beforeEach(async () => { @@ -736,7 +726,7 @@ describe('L1GNS', () => { }) }) - describe('multiple minting', async function () { + describe('multiple minting', function () { it('should mint less signal every time due to the bonding curve', async function () { const tokensToDepositMany = [ toGRT('1000'), // should mint if we start with number above minimum deposit @@ -1113,13 +1103,13 @@ describe('L1GNS', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, gns.address, - mockL2GNS.address, + l2GNSMock.address, expectedSentToL2, expectedCallhookData, ) await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(gns.address, mockL2Gateway.address, toBN(1), expectedL2Data) + .withArgs(gns.address, l2GRTGatewayMock.address, toBN(1), expectedL2Data) }) it('sends tokens and calldata for a legacy subgraph to L2 through the GRT bridge', async function () { const seqID = toBN('2') @@ -1160,13 +1150,13 @@ describe('L1GNS', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, legacyGNSMock.address, - mockL2GNS.address, + l2GNSMock.address, expectedSentToL2, expectedCallhookData, ) await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(legacyGNSMock.address, mockL2Gateway.address, toBN(1), expectedL2Data) + .withArgs(legacyGNSMock.address, l2GRTGatewayMock.address, toBN(1), expectedL2Data) }) it('rejects calls from someone who is not the subgraph owner', async function () { const subgraph0 = await publishAndCurateOnSubgraph() @@ -1365,7 +1355,7 @@ describe('L1GNS', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, gns.address, - mockL2GNS.address, + l2GNSMock.address, curatorTokens, expectedCallhookData, ) @@ -1390,7 +1380,7 @@ describe('L1GNS', () => { // seqNum (third argument in the event) is 2, because number 1 was when the subgraph was sent to L2 await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(gns.address, mockL2Gateway.address, toBN('2'), expectedL2Data) + .withArgs(gns.address, l2GRTGatewayMock.address, toBN('2'), expectedL2Data) await expect(tx) .emit(gns, 'CuratorBalanceSentToL2') .withArgs(subgraph0.id, other.address, another.address, curatorTokens) @@ -1407,7 +1397,7 @@ describe('L1GNS', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, gns.address, - mockL2GNS.address, + l2GNSMock.address, curatorTokens, expectedCallhookData, ) @@ -1432,7 +1422,7 @@ describe('L1GNS', () => { // seqNum (third argument in the event) is 2, because number 1 was when the subgraph was sent to L2 await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(gns.address, mockL2Gateway.address, toBN('2'), expectedL2Data) + .withArgs(gns.address, l2GRTGatewayMock.address, toBN('2'), expectedL2Data) const tx2 = gns .connect(other) @@ -1505,7 +1495,7 @@ describe('L1GNS', () => { const expectedL2Data1 = await l1GraphTokenGateway.getOutboundCalldata( grt.address, gns.address, - mockL2GNS.address, + l2GNSMock.address, curator1Tokens, expectedCallhookData1, ) @@ -1530,7 +1520,7 @@ describe('L1GNS', () => { // seqNum (third argument in the event) is 2, because number 1 was when the subgraph was sent to L2 await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(gns.address, mockL2Gateway.address, toBN('2'), expectedL2Data1) + .withArgs(gns.address, l2GRTGatewayMock.address, toBN('2'), expectedL2Data1) // Accept slight numerical errors given how we compute the amount of tokens to send const curator2TokensUpdated = (await gns.subgraphs(subgraph0.id)).withdrawableGRT @@ -1538,7 +1528,7 @@ describe('L1GNS', () => { const expectedL2Data2 = await l1GraphTokenGateway.getOutboundCalldata( grt.address, gns.address, - mockL2GNS.address, + l2GNSMock.address, curator2TokensUpdated, expectedCallhookData2, ) @@ -1557,7 +1547,7 @@ describe('L1GNS', () => { // seqNum (third argument in the event) is 3 now await expect(tx2) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(gns.address, mockL2Gateway.address, toBN('3'), expectedL2Data2) + .withArgs(gns.address, l2GRTGatewayMock.address, toBN('3'), expectedL2Data2) }) it('rejects calls for a subgraph that was not sent to L2', async function () { const subgraph0 = await publishAndCurateOnSubgraph() diff --git a/packages/contracts/test/governance/controller.test.ts b/packages/contracts/test/unit/governance/controller.test.ts similarity index 94% rename from packages/contracts/test/governance/controller.test.ts rename to packages/contracts/test/unit/governance/controller.test.ts index 1c08feb44..5b3074865 100644 --- a/packages/contracts/test/governance/controller.test.ts +++ b/packages/contracts/test/unit/governance/controller.test.ts @@ -2,8 +2,8 @@ import hre from 'hardhat' import { expect } from 'chai' import { constants, utils } from 'ethers' -import { Controller } from '../../build/types/Controller' -import { EpochManager } from '../../build/types/EpochManager' +import { Controller } from '../../../build/types/Controller' +import { EpochManager } from '../../../build/types/EpochManager' import { NetworkFixture } from '../lib/fixtures' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' @@ -25,14 +25,14 @@ describe('Managed', () => { let controller: Controller before(async function () { - ;[me, mockController, newMockEpochManager] = await graph.getTestAccounts() + [me, mockController, newMockEpochManager] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) // We just run the fixures to set up a contract with Managed, as this // is cleaner and easier for us to test fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) - epochManager = contracts.EpochManager as EpochManager - controller = contracts.Controller as Controller + epochManager = contracts.EpochManager + controller = contracts.Controller }) beforeEach(async function () { diff --git a/packages/contracts/test/governance/governed.test.ts b/packages/contracts/test/unit/governance/governed.test.ts similarity index 93% rename from packages/contracts/test/governance/governed.test.ts rename to packages/contracts/test/unit/governance/governed.test.ts index f26e4b911..fb94b343a 100644 --- a/packages/contracts/test/governance/governed.test.ts +++ b/packages/contracts/test/unit/governance/governed.test.ts @@ -2,7 +2,7 @@ import { expect } from 'chai' import hre from 'hardhat' import '@nomiclabs/hardhat-ethers' -import { Governed } from '../../build/types/Governed' +import { Governed } from '../../../build/types/Governed' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' const { ethers } = hre @@ -16,7 +16,7 @@ describe('Governed', () => { let governed: Governed beforeEach(async function () { - ;[me, governor] = await graph.getTestAccounts() + [me, governor] = await graph.getTestAccounts() const factory = await ethers.getContractFactory('GovernedMock') governed = (await factory.connect(governor).deploy()) as Governed diff --git a/packages/contracts/test/governance/pausing.test.ts b/packages/contracts/test/unit/governance/pausing.test.ts similarity index 93% rename from packages/contracts/test/governance/pausing.test.ts rename to packages/contracts/test/unit/governance/pausing.test.ts index c27a2f7c6..fbb9b3abc 100644 --- a/packages/contracts/test/governance/pausing.test.ts +++ b/packages/contracts/test/unit/governance/pausing.test.ts @@ -1,9 +1,8 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants } from 'ethers' -import { Controller } from '../../build/types/Controller' -import { IStaking } from '../../build/types/IStaking' +import { Controller } from '../../../build/types/Controller' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' import { GraphNetworkContracts, toGRT } from '@graphprotocol/sdk' @@ -31,14 +30,13 @@ describe('Pausing', () => { await expect(tx).emit(controller, 'PauseChanged').withArgs(setValue) expect(await controller.paused()).eq(setValue) } - const AddressZero = constants.AddressZero before(async function () { - ;[me] = await graph.getTestAccounts() + [me] = await graph.getTestAccounts() ;({ governor, pauseGuardian: guardian } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) staking = contracts.Staking as IStaking - controller = contracts.Controller as Controller + controller = contracts.Controller }) beforeEach(async function () { diff --git a/packages/contracts/test/graphToken.test.ts b/packages/contracts/test/unit/graphToken.test.ts similarity index 100% rename from packages/contracts/test/graphToken.test.ts rename to packages/contracts/test/unit/graphToken.test.ts diff --git a/packages/contracts/test/l2/l2Curation.test.ts b/packages/contracts/test/unit/l2/l2Curation.test.ts similarity index 93% rename from packages/contracts/test/l2/l2Curation.test.ts rename to packages/contracts/test/unit/l2/l2Curation.test.ts index 3375c72cd..f004318f1 100644 --- a/packages/contracts/test/l2/l2Curation.test.ts +++ b/packages/contracts/test/unit/l2/l2Curation.test.ts @@ -1,22 +1,22 @@ import hre from 'hardhat' import { expect } from 'chai' -import { utils, BigNumber, Event, Signer, constants } from 'ethers' +import { BigNumber, constants, Event, Signer, utils } from 'ethers' -import { L2Curation } from '../../build/types/L2Curation' -import { GraphToken } from '../../build/types/GraphToken' -import { Controller } from '../../build/types/Controller' +import { L2Curation } from '../../../build/types/L2Curation' +import { GraphToken } from '../../../build/types/GraphToken' +import { Controller } from '../../../build/types/Controller' import { NetworkFixture } from '../lib/fixtures' -import { GNS } from '../../build/types/GNS' +import { GNS } from '../../../build/types/GNS' import { parseEther } from 'ethers/lib/utils' import { formatGRT, + GraphNetworkContracts, + helpers, randomAddress, randomHexBytes, toBN, toGRT, - helpers, - GraphNetworkContracts, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' @@ -25,7 +25,7 @@ const { AddressZero } = constants const MAX_PPM = 1000000 const chunkify = (total: BigNumber, maxChunks = 10): Array => { - const chunks = [] + const chunks: BigNumber[] = [] while (total.gt(0) && maxChunks > 0) { const m = 1000000 const p = Math.floor(Math.random() * m) @@ -55,12 +55,12 @@ describe('L2Curation:Config', () => { let curation: L2Curation before(async function () { - ;[me] = await graph.getTestAccounts() + [me] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor, true) - curation = contracts.L2Curation as L2Curation + curation = contracts.L2Curation }) beforeEach(async function () { @@ -189,8 +189,8 @@ describe('L2Curation', () => { } const minSupply = signalAmountForMinimumCuration return ( - (await calcLinearBondingCurve(minSupply, minDeposit, depositAmount.sub(minDeposit))) + - toFloat(minSupply) + (await calcLinearBondingCurve(minSupply, minDeposit, depositAmount.sub(minDeposit))) + + toFloat(minSupply) ) } // Calculate bonding curve in the test @@ -343,13 +343,13 @@ describe('L2Curation', () => { before(async function () { // Use stakingMock so we can call collect - ;[me, curator, stakingMock] = await graph.getTestAccounts() + [me, curator, stakingMock] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor, true) curation = contracts.Curation as L2Curation grt = contracts.GraphToken as GraphToken - controller = contracts.Controller as Controller + controller = contracts.Controller gns = contracts.GNS as GNS gnsImpersonator = await helpers.impersonateAccount(gns.address) @@ -427,7 +427,7 @@ describe('L2Curation', () => { }) }) - describe('curate', async function () { + describe('curate', function () { it('reject deposit below minimum tokens required', async function () { // Set the minimum to a value greater than 1 so that we can test await curation.connect(governor).setMinimumCurationDeposit(toBN('2')) @@ -469,9 +469,50 @@ describe('L2Curation', () => { .mint(subgraphDeploymentID, tokensToDeposit, expectedSignal.add(1)) await expect(tx).revertedWith('Slippage protection') }) + + it('should pay a minimum of 1 wei GRT in tax when depositing small amounts', async function () { + // Set minimum curation deposit + await contracts.Curation.connect(governor).setMinimumCurationDeposit('1') + + // Set curation tax to 1% + await contracts.Curation.connect(governor).setCurationTaxPercentage(10000) + + // Deposit a small amount where tax would be less than 1 wei + const tokensToDeposit = '99' + + const expectedTokens = '98' + const expectedSignal = '98' + const expectedTax = 1 + + const tx = contracts.Curation.connect(curator).mint( + subgraphDeploymentID, + tokensToDeposit, + expectedSignal, + ) + + await expect(tx) + .emit(contracts.Curation, 'Signalled') + .withArgs( + curator.address, + subgraphDeploymentID, + tokensToDeposit, + expectedSignal, + expectedTax, + ) + + const burnTx = contracts.Curation.connect(curator).burn( + subgraphDeploymentID, + expectedSignal, + expectedTokens, + ) + + await expect(burnTx) + .emit(contracts.Curation, 'Burned') + .withArgs(curator.address, subgraphDeploymentID, expectedTokens, expectedSignal) + }) }) - describe('curate tax free (from GNS)', async function () { + describe('curate tax free (from GNS)', function () { it('can not be called by anyone other than GNS', async function () { const tokensToDeposit = await curation.minimumCurationDeposit() const tx = curation.connect(curator).mintTaxFree(subgraphDeploymentID, tokensToDeposit) @@ -514,8 +555,8 @@ describe('L2Curation', () => { }) }) - describe('collect', async function () { - context('> not curated', async function () { + describe('collect', function () { + context('> not curated', function () { it('reject collect tokens distributed to the curation pool', async function () { // Source of tokens must be the staking for this to work await controller @@ -528,7 +569,7 @@ describe('L2Curation', () => { }) }) - context('> curated', async function () { + context('> curated', function () { beforeEach(async function () { await curation.connect(curator).mint(subgraphDeploymentID, toGRT('1000'), 0) }) @@ -604,7 +645,7 @@ describe('L2Curation', () => { }) }) - describe('burn', async function () { + describe('burn', function () { beforeEach(async function () { await curation.connect(curator).mint(subgraphDeploymentID, tokensToDeposit, 0) }) @@ -683,7 +724,7 @@ describe('L2Curation', () => { }) }) - describe('conservation', async function () { + describe('conservation', function () { it('should match multiple deposits and redeems back to initial state', async function () { this.timeout(60000) // increase timeout for test runner @@ -720,7 +761,7 @@ describe('L2Curation', () => { }) }) - describe('multiple minting', async function () { + describe('multiple minting', function () { it('should mint the same signal every time due to the flat bonding curve', async function () { const tokensToDepositMany = [ toGRT('1000'), // should mint if we start with number above minimum deposit diff --git a/packages/contracts/test/l2/l2GNS.test.ts b/packages/contracts/test/unit/l2/l2GNS.test.ts similarity index 89% rename from packages/contracts/test/l2/l2GNS.test.ts rename to packages/contracts/test/unit/l2/l2GNS.test.ts index e014b2e07..496a4fe76 100644 --- a/packages/contracts/test/l2/l2GNS.test.ts +++ b/packages/contracts/test/unit/l2/l2GNS.test.ts @@ -1,12 +1,13 @@ +/* eslint-disable no-secrets/no-secrets */ import hre from 'hardhat' import { expect } from 'chai' -import { ethers, ContractTransaction, BigNumber } from 'ethers' +import { BigNumber, ContractTransaction, ethers } from 'ethers' import { defaultAbiCoder, parseEther } from 'ethers/lib/utils' -import { L2FixtureContracts, NetworkFixture } from '../lib/fixtures' +import { NetworkFixture } from '../lib/fixtures' -import { L2GNS } from '../../build/types/L2GNS' -import { L2GraphTokenGateway } from '../../build/types/L2GraphTokenGateway' +import { L2GNS } from '../../../build/types/L2GNS' +import { L2GraphTokenGateway } from '../../../build/types/L2GraphTokenGateway' import { burnSignal, DEFAULT_RESERVE_RATIO, @@ -15,8 +16,8 @@ import { publishNewSubgraph, publishNewVersion, } from '../lib/gnsUtils' -import { L2Curation } from '../../build/types/L2Curation' -import { GraphToken } from '../../build/types/GraphToken' +import { L2Curation } from '../../../build/types/L2Curation' +import { GraphToken } from '../../../build/types/GraphToken' import { buildSubgraph, buildSubgraphId, @@ -30,7 +31,8 @@ import { toGRT, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { IL2Staking } from '../../build/types/IL2Staking' +import { IL2Staking } from '../../../build/types/IL2Staking' +import { L1GNS, L1GraphTokenGateway } from '../../../build/types' const { HashZero } = ethers.constants @@ -47,14 +49,13 @@ describe('L2GNS', () => { let attacker: SignerWithAddress let other: SignerWithAddress let governor: SignerWithAddress - let mockRouter: SignerWithAddress - let mockL1GRT: SignerWithAddress - let mockL1Gateway: SignerWithAddress - let mockL1GNS: SignerWithAddress - let mockL1Staking: SignerWithAddress let fixture: NetworkFixture let fixtureContracts: GraphNetworkContracts + let l1MockContracts: GraphNetworkContracts + let l1GRTMock: GraphToken + let l1GNSMock: L1GNS + let l1GRTGatewayMock: L1GraphTokenGateway let l2GraphTokenGateway: L2GraphTokenGateway let gns: L2GNS let curation: L2Curation @@ -75,13 +76,13 @@ describe('L2GNS', () => { amount: BigNumber, callhookData: string, ): Promise { - const mockL1GatewayL2Alias = await helpers.getL2SignerFromL1(mockL1Gateway.address) + const l1GRTGatewayMockL2Alias = await helpers.getL2SignerFromL1(l1GRTGatewayMock.address) // Eth for gas: - await helpers.setBalance(await mockL1GatewayL2Alias.getAddress(), parseEther('1')) + await helpers.setBalance(await l1GRTGatewayMockL2Alias.getAddress(), parseEther('1')) const tx = l2GraphTokenGateway - .connect(mockL1GatewayL2Alias) - .finalizeInboundTransfer(mockL1GRT.address, from, to, amount, callhookData) + .connect(l1GRTGatewayMockL2Alias) + .finalizeInboundTransfer(l1GRTMock.address, from, to, amount, callhookData) return tx } @@ -103,7 +104,7 @@ describe('L2GNS', () => { ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookData) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookData) const l2SubgraphId = await gns.getAliasedL2SubgraphID(l1SubgraphId) await gns @@ -118,28 +119,32 @@ describe('L2GNS', () => { before(async function () { newSubgraph0 = buildSubgraph() - ;[me, attacker, other, mockRouter, mockL1GRT, mockL1Gateway, mockL1GNS, mockL1Staking] = - await graph.getTestAccounts() + ;[me, attacker, other] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) + + // Deploy L2 fixtureContracts = await fixture.load(governor, true) - l2GraphTokenGateway = fixtureContracts.L2GraphTokenGateway as L2GraphTokenGateway - gns = fixtureContracts.L2GNS as L2GNS + l2GraphTokenGateway = fixtureContracts.L2GraphTokenGateway + gns = fixtureContracts.L2GNS staking = fixtureContracts.L2Staking as unknown as IL2Staking - curation = fixtureContracts.L2Curation as L2Curation + curation = fixtureContracts.L2Curation grt = fixtureContracts.GraphToken as GraphToken + // Deploy L1 mock + l1MockContracts = await fixture.loadMock(false) + l1GRTMock = l1MockContracts.GraphToken as GraphToken + l1GNSMock = l1MockContracts.L1GNS + l1GRTGatewayMock = l1MockContracts.L1GraphTokenGateway + + // Deploy L2 arbitrum bridge + await fixture.loadL2ArbitrumBridge(governor) + + // Configure L2 bridge + await fixture.configureL2Bridge(governor, fixtureContracts, l1MockContracts) + await grt.connect(governor).mint(me.address, toGRT('10000')) - await fixture.configureL2Bridge( - governor, - fixtureContracts, - mockRouter.address, - mockL1GRT.address, - mockL1Gateway.address, - mockL1GNS.address, - mockL1Staking.address, - ) }) beforeEach(async function () { @@ -151,7 +156,7 @@ describe('L2GNS', () => { }) // Adapted from the L1 GNS tests but allowing curating to a pre-curated subgraph deployment - describe('publishNewVersion', async function () { + describe('publishNewVersion', function () { let subgraph: Subgraph beforeEach(async () => { @@ -261,7 +266,7 @@ describe('L2GNS', () => { ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - const tx = gns.connect(me).onTokenTransfer(mockL1GNS.address, curatedTokens, callhookData) + const tx = gns.connect(me).onTokenTransfer(l1GNSMock.address, curatedTokens, callhookData) await expect(tx).revertedWith('ONLY_GATEWAY') }) it('rejects calls if the L1 sender is not the L1GNS', async function () { @@ -281,7 +286,7 @@ describe('L2GNS', () => { [toBN(0), l1SubgraphId, me.address], ) const tx = gatewayFinalizeTransfer( - mockL1GNS.address, + l1GNSMock.address, gns.address, curatedTokens, callhookData, @@ -291,7 +296,7 @@ describe('L2GNS', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1GNS.address, gns.address, curatedTokens) + .withArgs(l1GRTMock.address, l1GNSMock.address, gns.address, curatedTokens) await expect(tx) .emit(gns, 'SubgraphReceivedFromL1') .withArgs(l1SubgraphId, l2SubgraphId, me.address, curatedTokens) @@ -321,7 +326,7 @@ describe('L2GNS', () => { [toBN(0), l1SubgraphId, me.address], ) const tx = gatewayFinalizeTransfer( - mockL1GNS.address, + l1GNSMock.address, gns.address, curatedTokens, callhookData, @@ -331,7 +336,7 @@ describe('L2GNS', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1GNS.address, gns.address, curatedTokens) + .withArgs(l1GRTMock.address, l1GNSMock.address, gns.address, curatedTokens) await expect(tx) .emit(gns, 'SubgraphReceivedFromL1') .withArgs(l1SubgraphId, l2SubgraphId, me.address, curatedTokens) @@ -365,13 +370,13 @@ describe('L2GNS', () => { describe('finishing a subgraph transfer from L1', function () { it('publishes the transferred subgraph and mints signal with no tax', async function () { - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() const callhookData = defaultAbiCoder.encode( ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookData) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookData) // Calculate expected signal before minting const expectedSignal = await curation.tokensToSignalNoTax( newSubgraph0.subgraphDeploymentID, @@ -411,8 +416,8 @@ describe('L2GNS', () => { .withArgs(l2SubgraphId, me.address, expectedNSignal, expectedSignal, curatedTokens) }) it('protects the owner against a rounding attack', async function () { - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() const collectTokens = curatedTokens.mul(20) await staking.connect(governor).setCurationPercentage(100000) @@ -447,7 +452,7 @@ describe('L2GNS', () => { ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookData) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookData) const l2SubgraphId = await gns.getAliasedL2SubgraphID(l1SubgraphId) const tx = gns @@ -472,13 +477,13 @@ describe('L2GNS', () => { await expect(tx).emit(gns, 'SubgraphL2TransferFinalized').withArgs(l2SubgraphId) }) it('cannot be called by someone other than the subgraph owner', async function () { - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() const callhookData = defaultAbiCoder.encode( ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookData) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookData) const l2SubgraphId = await gns.getAliasedL2SubgraphID(l1SubgraphId) const tx = gns .connect(other) @@ -519,13 +524,13 @@ describe('L2GNS', () => { await expect(tx).revertedWith('INVALID_SUBGRAPH') }) it('accepts calls to a pre-curated subgraph deployment', async function () { - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() const callhookData = defaultAbiCoder.encode( ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookData) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookData) const l2SubgraphId = await gns.getAliasedL2SubgraphID(l1SubgraphId) // Calculate expected signal before minting @@ -576,7 +581,7 @@ describe('L2GNS', () => { ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookData) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookData) const l2SubgraphId = await gns.getAliasedL2SubgraphID(l1SubgraphId) const tx = gns .connect(me) @@ -590,7 +595,7 @@ describe('L2GNS', () => { ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookData) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookData) const l2SubgraphId = await gns.getAliasedL2SubgraphID(l1SubgraphId) await gns .connect(me) @@ -614,12 +619,12 @@ describe('L2GNS', () => { }) describe('claiming a curator balance with a message from L1 (onTokenTransfer)', function () { it('assigns a curator balance to a beneficiary', async function () { - const mockL1GNSL2Alias = await helpers.getL2SignerFromL1(mockL1GNS.address) + const l1GNSMockL2Alias = await helpers.getL2SignerFromL1(l1GNSMock.address) // Eth for gas: - await helpers.setBalance(await mockL1GNSL2Alias.getAddress(), parseEther('1')) + await helpers.setBalance(await l1GNSMockL2Alias.getAddress(), parseEther('1')) - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() await transferMockSubgraphFromL1( l1SubgraphId, curatedTokens, @@ -635,7 +640,7 @@ describe('L2GNS', () => { [toBN(1), l1SubgraphId, other.address], ) const tx = await gatewayFinalizeTransfer( - mockL1GNS.address, + l1GNSMock.address, gns.address, newCuratorTokens, callhookData, @@ -655,12 +660,12 @@ describe('L2GNS', () => { expect(l2NewCuratorSignal).eq(expectedNewCuratorSignal) }) it('adds the signal to any existing signal for the beneficiary', async function () { - const mockL1GNSL2Alias = await helpers.getL2SignerFromL1(mockL1GNS.address) + const l1GNSMockL2Alias = await helpers.getL2SignerFromL1(l1GNSMock.address) // Eth for gas: - await helpers.setBalance(await mockL1GNSL2Alias.getAddress(), parseEther('1')) + await helpers.setBalance(await l1GNSMockL2Alias.getAddress(), parseEther('1')) - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() await transferMockSubgraphFromL1( l1SubgraphId, curatedTokens, @@ -680,7 +685,7 @@ describe('L2GNS', () => { [toBN(1), l1SubgraphId, other.address], ) const tx = await gatewayFinalizeTransfer( - mockL1GNS.address, + l1GNSMock.address, gns.address, newCuratorTokens, callhookData, @@ -698,8 +703,8 @@ describe('L2GNS', () => { expect(l2CuratorBalance).eq(prevSignal.add(expectedNewCuratorSignal)) }) it('cannot be called by someone other than the L2GraphTokenGateway', async function () { - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() await transferMockSubgraphFromL1( l1SubgraphId, curatedTokens, @@ -710,12 +715,12 @@ describe('L2GNS', () => { ['uint8', 'uint256', 'address'], [toBN(1), l1SubgraphId, me.address], ) - const tx = gns.connect(me).onTokenTransfer(mockL1GNS.address, toGRT('1'), callhookData) + const tx = gns.connect(me).onTokenTransfer(l1GNSMock.address, toGRT('1'), callhookData) await expect(tx).revertedWith('ONLY_GATEWAY') }) it('rejects calls if the L1 sender is not the L1GNS', async function () { - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() await transferMockSubgraphFromL1( l1SubgraphId, curatedTokens, @@ -731,9 +736,9 @@ describe('L2GNS', () => { await expect(tx).revertedWith('ONLY_L1_GNS_THROUGH_BRIDGE') }) it('if a subgraph does not exist, it returns the tokens to the beneficiary', async function () { - const mockL1GNSL2Alias = await helpers.getL2SignerFromL1(mockL1GNS.address) + const l1GNSMockL2Alias = await helpers.getL2SignerFromL1(l1GNSMock.address) // Eth for gas: - await helpers.setBalance(await mockL1GNSL2Alias.getAddress(), parseEther('1')) + await helpers.setBalance(await l1GNSMockL2Alias.getAddress(), parseEther('1')) const { l1SubgraphId } = await defaultL1SubgraphParams() @@ -743,7 +748,7 @@ describe('L2GNS', () => { ) const curatorTokensBefore = await grt.balanceOf(me.address) const gnsBalanceBefore = await grt.balanceOf(gns.address) - const tx = gatewayFinalizeTransfer(mockL1GNS.address, gns.address, toGRT('1'), callhookData) + const tx = gatewayFinalizeTransfer(l1GNSMock.address, gns.address, toGRT('1'), callhookData) await expect(tx) .emit(gns, 'CuratorBalanceReturnedToBeneficiary') .withArgs(l1SubgraphId, me.address, toGRT('1')) @@ -757,9 +762,9 @@ describe('L2GNS', () => { it('for an L2-native subgraph, it sends the tokens to the beneficiary', async function () { // This should never really happen unless there's a clash in subgraph IDs (which should // also never happen), but we test it anyway to ensure it's a well-defined behavior - const mockL1GNSL2Alias = await helpers.getL2SignerFromL1(mockL1GNS.address) + const l1GNSMockL2Alias = await helpers.getL2SignerFromL1(l1GNSMock.address) // Eth for gas: - await helpers.setBalance(await mockL1GNSL2Alias.getAddress(), parseEther('1')) + await helpers.setBalance(await l1GNSMockL2Alias.getAddress(), parseEther('1')) const l2Subgraph = await publishNewSubgraph(me, newSubgraph0, gns, graph.chainId) @@ -769,7 +774,7 @@ describe('L2GNS', () => { ) const curatorTokensBefore = await grt.balanceOf(me.address) const gnsBalanceBefore = await grt.balanceOf(gns.address) - const tx = gatewayFinalizeTransfer(mockL1GNS.address, gns.address, toGRT('1'), callhookData) + const tx = gatewayFinalizeTransfer(l1GNSMock.address, gns.address, toGRT('1'), callhookData) await expect(tx) .emit(gns, 'CuratorBalanceReturnedToBeneficiary') .withArgs(l2Subgraph.id, me.address, toGRT('1')) @@ -781,16 +786,16 @@ describe('L2GNS', () => { expect(gnsBalanceAfter).eq(gnsBalanceBefore) }) it('if a subgraph transfer was not finished, it returns the tokens to the beneficiary', async function () { - const mockL1GNSL2Alias = await helpers.getL2SignerFromL1(mockL1GNS.address) + const l1GNSMockL2Alias = await helpers.getL2SignerFromL1(l1GNSMock.address) // Eth for gas: - await helpers.setBalance(await mockL1GNSL2Alias.getAddress(), parseEther('1')) + await helpers.setBalance(await l1GNSMockL2Alias.getAddress(), parseEther('1')) const { l1SubgraphId, curatedTokens } = await defaultL1SubgraphParams() const callhookDataSG = defaultAbiCoder.encode( ['uint8', 'uint256', 'address'], [toBN(0), l1SubgraphId, me.address], ) - await gatewayFinalizeTransfer(mockL1GNS.address, gns.address, curatedTokens, callhookDataSG) + await gatewayFinalizeTransfer(l1GNSMock.address, gns.address, curatedTokens, callhookDataSG) // At this point the SG exists, but transfer is not finished @@ -800,7 +805,7 @@ describe('L2GNS', () => { ) const curatorTokensBefore = await grt.balanceOf(me.address) const gnsBalanceBefore = await grt.balanceOf(gns.address) - const tx = gatewayFinalizeTransfer(mockL1GNS.address, gns.address, toGRT('1'), callhookData) + const tx = gatewayFinalizeTransfer(l1GNSMock.address, gns.address, toGRT('1'), callhookData) await expect(tx) .emit(gns, 'CuratorBalanceReturnedToBeneficiary') .withArgs(l1SubgraphId, me.address, toGRT('1')) @@ -853,7 +858,7 @@ describe('L2GNS', () => { const curatorTokensBefore = await grt.balanceOf(me.address) const gnsBalanceBefore = await grt.balanceOf(gns.address) const tx = gatewayFinalizeTransfer( - mockL1GNS.address, + l1GNSMock.address, gns.address, curatorTokens, callhookData, @@ -870,12 +875,12 @@ describe('L2GNS', () => { }) it('if a subgraph was deprecated after transfer, it returns the tokens to the beneficiary', async function () { - const mockL1GNSL2Alias = await helpers.getL2SignerFromL1(mockL1GNS.address) + const l1GNSMockL2Alias = await helpers.getL2SignerFromL1(l1GNSMock.address) // Eth for gas: - await helpers.setBalance(await mockL1GNSL2Alias.getAddress(), parseEther('1')) + await helpers.setBalance(await l1GNSMockL2Alias.getAddress(), parseEther('1')) - const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } = - await defaultL1SubgraphParams() + const { l1SubgraphId, curatedTokens, subgraphMetadata, versionMetadata } + = await defaultL1SubgraphParams() await transferMockSubgraphFromL1( l1SubgraphId, curatedTokens, @@ -893,7 +898,7 @@ describe('L2GNS', () => { ) const curatorTokensBefore = await grt.balanceOf(me.address) const gnsBalanceBefore = await grt.balanceOf(gns.address) - const tx = gatewayFinalizeTransfer(mockL1GNS.address, gns.address, toGRT('1'), callhookData) + const tx = gatewayFinalizeTransfer(l1GNSMock.address, gns.address, toGRT('1'), callhookData) await expect(tx) .emit(gns, 'CuratorBalanceReturnedToBeneficiary') .withArgs(l1SubgraphId, me.address, toGRT('1')) @@ -914,7 +919,7 @@ describe('L2GNS', () => { ['uint8', 'uint256', 'address'], [toBN(2), toBN(1337), me.address], ) - const tx = gatewayFinalizeTransfer(mockL1GNS.address, gns.address, toGRT('1'), callhookData) + const tx = gatewayFinalizeTransfer(l1GNSMock.address, gns.address, toGRT('1'), callhookData) await expect(tx).revertedWith('INVALID_CODE') }) }) diff --git a/packages/contracts/test/l2/l2GraphToken.test.ts b/packages/contracts/test/unit/l2/l2GraphToken.test.ts similarity index 84% rename from packages/contracts/test/l2/l2GraphToken.test.ts rename to packages/contracts/test/unit/l2/l2GraphToken.test.ts index 0af174e04..3b2fe2021 100644 --- a/packages/contracts/test/l2/l2GraphToken.test.ts +++ b/packages/contracts/test/unit/l2/l2GraphToken.test.ts @@ -1,11 +1,11 @@ import hre from 'hardhat' import { expect } from 'chai' -import { L2GraphToken } from '../../build/types/L2GraphToken' +import { L2GraphToken } from '../../../build/types/L2GraphToken' import { grtTests } from '../lib/graphTokenTests' import { NetworkFixture } from '../lib/fixtures' -import { toGRT, helpers, GraphNetworkContracts } from '@graphprotocol/sdk' +import { GraphNetworkContracts, toGRT } from '@graphprotocol/sdk' import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' describe('L2GraphToken', () => { @@ -24,11 +24,11 @@ describe('L2GraphToken', () => { let grt: L2GraphToken before(async function () { - ;[mockL1GRT, mockL2Gateway, user] = await graph.getTestAccounts() + [mockL1GRT, mockL2Gateway, user] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor, true) - grt = contracts.L2GraphToken as L2GraphToken + grt = contracts.L2GraphToken }) beforeEach(async function () { @@ -39,7 +39,7 @@ describe('L2GraphToken', () => { await fixture.tearDown() }) - describe('setGateway', async function () { + describe('setGateway', function () { it('cannot be called by someone who is not the governor', async function () { const tx = grt.connect(mockL2Gateway).setGateway(mockL2Gateway.address) await expect(tx).revertedWith('Only Governor can call') @@ -47,10 +47,10 @@ describe('L2GraphToken', () => { it('sets the L2 Gateway address when called by the governor', async function () { const tx = grt.connect(governor).setGateway(mockL2Gateway.address) await expect(tx).emit(grt, 'GatewaySet').withArgs(mockL2Gateway.address) - await expect(await grt.gateway()).eq(mockL2Gateway.address) + expect(await grt.gateway()).eq(mockL2Gateway.address) }) }) - describe('setL1Address', async function () { + describe('setL1Address', function () { it('cannot be called by someone who is not the governor', async function () { const tx = grt.connect(mockL2Gateway).setL1Address(mockL1GRT.address) await expect(tx).revertedWith('Only Governor can call') @@ -58,16 +58,16 @@ describe('L2GraphToken', () => { it('sets the L1 GRT address when called by the governor', async function () { const tx = grt.connect(governor).setL1Address(mockL1GRT.address) await expect(tx).emit(grt, 'L1AddressSet').withArgs(mockL1GRT.address) - await expect(await grt.l1Address()).eq(mockL1GRT.address) + expect(await grt.l1Address()).eq(mockL1GRT.address) }) }) - describe('bridge minting and burning', async function () { + describe('bridge minting and burning', function () { beforeEach(async function () { // Configure the l1Address and gateway await grt.connect(governor).setL1Address(mockL1GRT.address) await grt.connect(governor).setGateway(mockL2Gateway.address) }) - describe('bridgeMint', async function () { + describe('bridgeMint', function () { it('cannot be called by someone who is not the gateway', async function () { const tx = grt.connect(governor).bridgeMint(user.address, toGRT('100')) await expect(tx).revertedWith('NOT_GATEWAY') @@ -75,10 +75,10 @@ describe('L2GraphToken', () => { it('mints GRT into a destination account', async function () { const tx = grt.connect(mockL2Gateway).bridgeMint(user.address, toGRT('100')) await expect(tx).emit(grt, 'BridgeMinted').withArgs(user.address, toGRT('100')) - await expect(await grt.balanceOf(user.address)).eq(toGRT('100')) + expect(await grt.balanceOf(user.address)).eq(toGRT('100')) }) }) - describe('bridgeBurn', async function () { + describe('bridgeBurn', function () { it('cannot be called by someone who is not the gateway', async function () { const tx = grt.connect(governor).bridgeBurn(user.address, toGRT('100')) await expect(tx).revertedWith('NOT_GATEWAY') @@ -99,7 +99,7 @@ describe('L2GraphToken', () => { await grt.connect(user).approve(mockL2Gateway.address, toGRT('20')) const tx = grt.connect(mockL2Gateway).bridgeBurn(user.address, toGRT('20')) await expect(tx).emit(grt, 'BridgeBurned').withArgs(user.address, toGRT('20')) - await expect(await grt.balanceOf(user.address)).eq(toGRT('80')) + expect(await grt.balanceOf(user.address)).eq(toGRT('80')) }) }) it('does not allow the bridge to mint as a regular minter', async function () { diff --git a/packages/contracts/test/l2/l2GraphTokenGateway.test.ts b/packages/contracts/test/unit/l2/l2GraphTokenGateway.test.ts similarity index 74% rename from packages/contracts/test/l2/l2GraphTokenGateway.test.ts rename to packages/contracts/test/unit/l2/l2GraphTokenGateway.test.ts index 1c3ffa4cc..5718cf571 100644 --- a/packages/contracts/test/l2/l2GraphTokenGateway.test.ts +++ b/packages/contracts/test/unit/l2/l2GraphTokenGateway.test.ts @@ -1,20 +1,21 @@ import hre from 'hardhat' import { expect, use } from 'chai' -import { constants, ContractTransaction, Signer, utils } from 'ethers' +import { constants, ContractTransaction, Signer, utils, Wallet } from 'ethers' -import { L2GraphToken } from '../../build/types/L2GraphToken' -import { L2GraphTokenGateway } from '../../build/types/L2GraphTokenGateway' -import { CallhookReceiverMock } from '../../build/types/CallhookReceiverMock' +import { L2GraphToken } from '../../../build/types/L2GraphToken' +import { L2GraphTokenGateway } from '../../../build/types/L2GraphTokenGateway' +import { CallhookReceiverMock } from '../../../build/types/CallhookReceiverMock' -import { L2FixtureContracts, NetworkFixture } from '../lib/fixtures' +import { NetworkFixture } from '../lib/fixtures' import { FakeContract, smock } from '@defi-wonderland/smock' use(smock.matchers) -import { RewardsManager } from '../../build/types/RewardsManager' -import { DeployType, GraphNetworkContracts, deploy, helpers, toBN, toGRT } from '@graphprotocol/sdk' +import { RewardsManager } from '../../../build/types/RewardsManager' +import { deploy, DeployType, GraphNetworkContracts, helpers, toBN, toGRT } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { GraphToken, L1GraphTokenGateway } from '../../../build/types' const { AddressZero } = constants @@ -25,16 +26,16 @@ describe('L2GraphTokenGateway', () => { let tokenSender: SignerWithAddress let l1Receiver: SignerWithAddress let l2Receiver: SignerWithAddress - let mockRouter: SignerWithAddress - let mockL1GRT: SignerWithAddress - let mockL1Gateway: SignerWithAddress let pauseGuardian: SignerWithAddress - let mockL1GNS: SignerWithAddress - let mockL1Staking: SignerWithAddress let fixture: NetworkFixture let arbSysMock: FakeContract let fixtureContracts: GraphNetworkContracts + let l1MockContracts: GraphNetworkContracts + let l1GRTMock: GraphToken + let l1GRTGatewayMock: L1GraphTokenGateway + let routerMock: Wallet + let grt: L2GraphToken let l2GraphTokenGateway: L2GraphTokenGateway let callhookReceiverMock: CallhookReceiverMock @@ -48,25 +49,24 @@ describe('L2GraphTokenGateway', () => { ) before(async function () { - ;[ - me, - governor, - tokenSender, - l1Receiver, - mockRouter, - mockL1GRT, - mockL1Gateway, - l2Receiver, - pauseGuardian, - mockL1GNS, - mockL1Staking, - ] = await graph.getTestAccounts() + [me, governor, tokenSender, l1Receiver, l2Receiver, pauseGuardian] + = await graph.getTestAccounts() fixture = new NetworkFixture(graph.provider) + + // Deploy L2 fixtureContracts = await fixture.load(governor, true) grt = fixtureContracts.GraphToken as L2GraphToken - l2GraphTokenGateway = fixtureContracts.L2GraphTokenGateway as L2GraphTokenGateway - rewardsManager = fixtureContracts.RewardsManager as RewardsManager + l2GraphTokenGateway = fixtureContracts.L2GraphTokenGateway + rewardsManager = fixtureContracts.RewardsManager + + // Deploy L2 arbitrum bridge + ;({ routerMock } = await fixture.loadL2ArbitrumBridge(governor)) + + // Deploy L1 mock + l1MockContracts = await fixture.loadMock(false) + l1GRTMock = l1MockContracts.GraphToken as GraphToken + l1GRTGatewayMock = l1MockContracts.L1GraphTokenGateway callhookReceiverMock = ( await deploy(DeployType.Deploy, governor, { @@ -74,8 +74,9 @@ describe('L2GraphTokenGateway', () => { }) ).contract as CallhookReceiverMock - // Give some funds to the token sender + // Give some funds to the token sender and router mock await grt.connect(governor).mint(tokenSender.address, senderTokens) + await helpers.setBalance(routerMock.address, utils.parseEther('1')) }) beforeEach(async function () { @@ -101,8 +102,7 @@ describe('L2GraphTokenGateway', () => { describe('outboundTransfer', function () { it('reverts because it is paused', async function () { const tx = l2GraphTokenGateway - .connect(tokenSender) - ['outboundTransfer(address,address,uint256,bytes)']( + .connect(tokenSender)['outboundTransfer(address,address,uint256,bytes)']( grt.address, l1Receiver.address, toGRT('10'), @@ -129,25 +129,25 @@ describe('L2GraphTokenGateway', () => { describe('setL2Router', function () { it('is not callable by addreses that are not the governor', async function () { - const tx = l2GraphTokenGateway.connect(tokenSender).setL2Router(mockRouter.address) + const tx = l2GraphTokenGateway.connect(tokenSender).setL2Router(routerMock.address) await expect(tx).revertedWith('Only Controller governor') }) it('sets router address', async function () { - const tx = l2GraphTokenGateway.connect(governor).setL2Router(mockRouter.address) - await expect(tx).emit(l2GraphTokenGateway, 'L2RouterSet').withArgs(mockRouter.address) - expect(await l2GraphTokenGateway.l2Router()).eq(mockRouter.address) + const tx = l2GraphTokenGateway.connect(governor).setL2Router(routerMock.address) + await expect(tx).emit(l2GraphTokenGateway, 'L2RouterSet').withArgs(routerMock.address) + expect(await l2GraphTokenGateway.l2Router()).eq(routerMock.address) }) }) describe('setL1TokenAddress', function () { it('is not callable by addreses that are not the governor', async function () { - const tx = l2GraphTokenGateway.connect(tokenSender).setL1TokenAddress(mockL1GRT.address) + const tx = l2GraphTokenGateway.connect(tokenSender).setL1TokenAddress(l1GRTMock.address) await expect(tx).revertedWith('Only Controller governor') }) it('sets l2GRT', async function () { - const tx = l2GraphTokenGateway.connect(governor).setL1TokenAddress(mockL1GRT.address) - await expect(tx).emit(l2GraphTokenGateway, 'L1TokenAddressSet').withArgs(mockL1GRT.address) - expect(await l2GraphTokenGateway.l1GRT()).eq(mockL1GRT.address) + const tx = l2GraphTokenGateway.connect(governor).setL1TokenAddress(l1GRTMock.address) + await expect(tx).emit(l2GraphTokenGateway, 'L1TokenAddressSet').withArgs(l1GRTMock.address) + expect(await l2GraphTokenGateway.l1GRT()).eq(l1GRTMock.address) }) }) @@ -155,17 +155,17 @@ describe('L2GraphTokenGateway', () => { it('is not callable by addreses that are not the governor', async function () { const tx = l2GraphTokenGateway .connect(tokenSender) - .setL1CounterpartAddress(mockL1Gateway.address) + .setL1CounterpartAddress(l1GRTGatewayMock.address) await expect(tx).revertedWith('Only Controller governor') }) it('sets L1Counterpart', async function () { const tx = l2GraphTokenGateway .connect(governor) - .setL1CounterpartAddress(mockL1Gateway.address) + .setL1CounterpartAddress(l1GRTGatewayMock.address) await expect(tx) .emit(l2GraphTokenGateway, 'L1CounterpartAddressSet') - .withArgs(mockL1Gateway.address) - expect(await l2GraphTokenGateway.l1Counterpart()).eq(mockL1Gateway.address) + .withArgs(l1GRTGatewayMock.address) + expect(await l2GraphTokenGateway.l1Counterpart()).eq(l1GRTGatewayMock.address) }) }) describe('Pausable behavior', () => { @@ -178,29 +178,23 @@ describe('L2GraphTokenGateway', () => { it('cannot be paused if some state variables are not set', async function () { let tx = l2GraphTokenGateway.connect(governor).setPaused(false) await expect(tx).revertedWith('L2_ROUTER_NOT_SET') - await l2GraphTokenGateway.connect(governor).setL2Router(mockRouter.address) + await l2GraphTokenGateway.connect(governor).setL2Router(routerMock.address) tx = l2GraphTokenGateway.connect(governor).setPaused(false) await expect(tx).revertedWith('L1_COUNTERPART_NOT_SET') - await l2GraphTokenGateway.connect(governor).setL1CounterpartAddress(mockL1Gateway.address) + await l2GraphTokenGateway + .connect(governor) + .setL1CounterpartAddress(l1GRTGatewayMock.address) tx = l2GraphTokenGateway.connect(governor).setPaused(false) await expect(tx).revertedWith('L1_GRT_NOT_SET') }) it('can be paused and unpaused by the governor', async function () { - await fixture.configureL2Bridge( - governor, - fixtureContracts, - mockRouter.address, - mockL1GRT.address, - mockL1Gateway.address, - mockL1GNS.address, - mockL1Staking.address, - ) + await fixture.configureL2Bridge(governor, fixtureContracts, l1MockContracts) let tx = l2GraphTokenGateway.connect(governor).setPaused(true) await expect(tx).emit(l2GraphTokenGateway, 'PauseChanged').withArgs(true) - await expect(await l2GraphTokenGateway.paused()).eq(true) + expect(await l2GraphTokenGateway.paused()).eq(true) tx = l2GraphTokenGateway.connect(governor).setPaused(false) await expect(tx).emit(l2GraphTokenGateway, 'PauseChanged').withArgs(false) - await expect(await l2GraphTokenGateway.paused()).eq(false) + expect(await l2GraphTokenGateway.paused()).eq(false) }) describe('setPauseGuardian', function () { it('cannot be called by someone other than governor', async function () { @@ -217,22 +211,14 @@ describe('L2GraphTokenGateway', () => { .withArgs(currentPauseGuardian, pauseGuardian.address) }) it('allows a pause guardian to pause and unpause', async function () { - await fixture.configureL2Bridge( - governor, - fixtureContracts, - mockRouter.address, - mockL1GRT.address, - mockL1Gateway.address, - mockL1GNS.address, - mockL1Staking.address, - ) + await fixture.configureL2Bridge(governor, fixtureContracts, l1MockContracts) await l2GraphTokenGateway.connect(governor).setPauseGuardian(pauseGuardian.address) let tx = l2GraphTokenGateway.connect(pauseGuardian).setPaused(true) await expect(tx).emit(l2GraphTokenGateway, 'PauseChanged').withArgs(true) - await expect(await l2GraphTokenGateway.paused()).eq(true) + expect(await l2GraphTokenGateway.paused()).eq(true) tx = l2GraphTokenGateway.connect(pauseGuardian).setPaused(false) await expect(tx).emit(l2GraphTokenGateway, 'PauseChanged').withArgs(false) - await expect(await l2GraphTokenGateway.paused()).eq(false) + expect(await l2GraphTokenGateway.paused()).eq(false) }) }) }) @@ -241,9 +227,8 @@ describe('L2GraphTokenGateway', () => { context('> after configuring and unpausing', function () { const testValidOutboundTransfer = async function (signer: Signer, data: string) { const tx = l2GraphTokenGateway - .connect(signer) - ['outboundTransfer(address,address,uint256,bytes)']( - mockL1GRT.address, + .connect(signer)['outboundTransfer(address,address,uint256,bytes)']( + l1GRTMock.address, l1Receiver.address, toGRT('10'), data, @@ -252,7 +237,7 @@ describe('L2GraphTokenGateway', () => { await expect(tx) .emit(l2GraphTokenGateway, 'WithdrawalInitiated') .withArgs( - mockL1GRT.address, + l1GRTMock.address, tokenSender.address, l1Receiver.address, expectedId, @@ -262,7 +247,7 @@ describe('L2GraphTokenGateway', () => { // Should use the L1 Gateway's interface, but both come from ITokenGateway const calldata = l2GraphTokenGateway.interface.encodeFunctionData('finalizeInboundTransfer', [ - mockL1GRT.address, + l1GRTMock.address, tokenSender.address, l1Receiver.address, toGRT('10'), @@ -270,31 +255,23 @@ describe('L2GraphTokenGateway', () => { ]) await expect(tx) .emit(l2GraphTokenGateway, 'TxToL1') - .withArgs(tokenSender.address, mockL1Gateway.address, 1, calldata) + .withArgs(tokenSender.address, l1GRTGatewayMock.address, 1, calldata) // For some reason the call count doesn't work properly, // and each function call is counted 12 times. // Possibly related to https://github.com/defi-wonderland/smock/issues/85 ? - //expect(arbSysMock.sendTxToL1).to.have.been.calledOnce - expect(arbSysMock.sendTxToL1).to.have.been.calledWith(mockL1Gateway.address, calldata) + // expect(arbSysMock.sendTxToL1).to.have.been.calledOnce + expect(arbSysMock.sendTxToL1).to.have.been.calledWith(l1GRTGatewayMock.address, calldata) const senderBalance = await grt.balanceOf(tokenSender.address) - await expect(senderBalance).eq(toGRT('990')) + expect(senderBalance).eq(toGRT('990')) } before(async function () { - await fixture.configureL2Bridge( - governor, - fixtureContracts, - mockRouter.address, - mockL1GRT.address, - mockL1Gateway.address, - mockL1GNS.address, - mockL1Staking.address, - ) + await fixture.configureL2Bridge(governor, fixtureContracts, l1MockContracts) }) describe('calculateL2TokenAddress', function () { it('returns the L2 token address', async function () { - expect(await l2GraphTokenGateway.calculateL2TokenAddress(mockL1GRT.address)).eq(grt.address) + expect(await l2GraphTokenGateway.calculateL2TokenAddress(l1GRTMock.address)).eq(grt.address) }) it('returns the zero address if the input is any other address', async function () { expect(await l2GraphTokenGateway.calculateL2TokenAddress(tokenSender.address)).eq( @@ -306,8 +283,7 @@ describe('L2GraphTokenGateway', () => { describe('outboundTransfer', function () { it('reverts when called with the wrong token address', async function () { const tx = l2GraphTokenGateway - .connect(tokenSender) - ['outboundTransfer(address,address,uint256,bytes)']( + .connect(tokenSender)['outboundTransfer(address,address,uint256,bytes)']( tokenSender.address, l1Receiver.address, toGRT('10'), @@ -325,14 +301,13 @@ describe('L2GraphTokenGateway', () => { ['address', 'bytes'], [tokenSender.address, defaultData], ) - await testValidOutboundTransfer(mockRouter, routerEncodedData) + await testValidOutboundTransfer(routerMock, routerEncodedData) }) it('reverts when called with nonempty calldata', async function () { await grt.connect(tokenSender).approve(l2GraphTokenGateway.address, toGRT('10')) const tx = l2GraphTokenGateway - .connect(tokenSender) - ['outboundTransfer(address,address,uint256,bytes)']( - mockL1GRT.address, + .connect(tokenSender)['outboundTransfer(address,address,uint256,bytes)']( + l1GRTMock.address, l1Receiver.address, toGRT('10'), defaultDataWithNotEmptyCallHookData, @@ -342,9 +317,8 @@ describe('L2GraphTokenGateway', () => { it('reverts when the sender does not have enough GRT', async function () { await grt.connect(tokenSender).approve(l2GraphTokenGateway.address, toGRT('1001')) const tx = l2GraphTokenGateway - .connect(tokenSender) - ['outboundTransfer(address,address,uint256,bytes)']( - mockL1GRT.address, + .connect(tokenSender)['outboundTransfer(address,address,uint256,bytes)']( + l1GRTMock.address, l1Receiver.address, toGRT('1001'), defaultData, @@ -359,33 +333,33 @@ describe('L2GraphTokenGateway', () => { to?: string, ): Promise { to = to ?? l2Receiver.address - const mockL1GatewayL2Alias = await helpers.getL2SignerFromL1(mockL1Gateway.address) + const l1GRTGatewayMockL2Alias = await helpers.getL2SignerFromL1(l1GRTGatewayMock.address) await me.sendTransaction({ - to: await mockL1GatewayL2Alias.getAddress(), + to: await l1GRTGatewayMockL2Alias.getAddress(), value: utils.parseUnits('1', 'ether'), }) const tx = l2GraphTokenGateway - .connect(mockL1GatewayL2Alias) - .finalizeInboundTransfer(mockL1GRT.address, tokenSender.address, to, toGRT('10'), data) + .connect(l1GRTGatewayMockL2Alias) + .finalizeInboundTransfer(l1GRTMock.address, tokenSender.address, to, toGRT('10'), data) await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, tokenSender.address, to, toGRT('10')) + .withArgs(l1GRTMock.address, tokenSender.address, to, toGRT('10')) await expect(tx).emit(grt, 'BridgeMinted').withArgs(to, toGRT('10')) // Unchanged const senderBalance = await grt.balanceOf(tokenSender.address) - await expect(senderBalance).eq(toGRT('1000')) + expect(senderBalance).eq(toGRT('1000')) // 10 newly minted GRT const receiverBalance = await grt.balanceOf(to) - await expect(receiverBalance).eq(toGRT('10')) + expect(receiverBalance).eq(toGRT('10')) return tx } it('reverts when called by an account that is not the gateway', async function () { const tx = l2GraphTokenGateway .connect(tokenSender) .finalizeInboundTransfer( - mockL1GRT.address, + l1GRTMock.address, tokenSender.address, l2Receiver.address, toGRT('10'), @@ -394,10 +368,11 @@ describe('L2GraphTokenGateway', () => { await expect(tx).revertedWith('ONLY_COUNTERPART_GATEWAY') }) it('reverts when called by an account that is the gateway but without the L2 alias', async function () { + const impersonatedGateway = await helpers.impersonateAccount(l1GRTGatewayMock.address) const tx = l2GraphTokenGateway - .connect(mockL1Gateway) + .connect(impersonatedGateway) .finalizeInboundTransfer( - mockL1GRT.address, + l1GRTMock.address, tokenSender.address, l2Receiver.address, toGRT('10'), @@ -424,15 +399,15 @@ describe('L2GraphTokenGateway', () => { ['uint256', 'uint256'], [toBN('0'), toBN('42')], ) - const mockL1GatewayL2Alias = await helpers.getL2SignerFromL1(mockL1Gateway.address) + const l1GRTGatewayMockL2Alias = await helpers.getL2SignerFromL1(l1GRTGatewayMock.address) await me.sendTransaction({ - to: await mockL1GatewayL2Alias.getAddress(), + to: await l1GRTGatewayMockL2Alias.getAddress(), value: utils.parseUnits('1', 'ether'), }) const tx = l2GraphTokenGateway - .connect(mockL1GatewayL2Alias) + .connect(l1GRTGatewayMockL2Alias) .finalizeInboundTransfer( - mockL1GRT.address, + l1GRTMock.address, tokenSender.address, callhookReceiverMock.address, toGRT('10'), @@ -442,23 +417,23 @@ describe('L2GraphTokenGateway', () => { }) it('reverts if trying to call a callhook in a contract that does not implement onTokenTransfer', async function () { const callHookData = utils.defaultAbiCoder.encode(['uint256'], [toBN('0')]) - const mockL1GatewayL2Alias = await helpers.getL2SignerFromL1(mockL1Gateway.address) + const l1GRTGatewayMockL2Alias = await helpers.getL2SignerFromL1(l1GRTGatewayMock.address) await me.sendTransaction({ - to: await mockL1GatewayL2Alias.getAddress(), + to: await l1GRTGatewayMockL2Alias.getAddress(), value: utils.parseUnits('1', 'ether'), }) // RewardsManager does not implement onTokenTransfer, so this will fail const tx = l2GraphTokenGateway - .connect(mockL1GatewayL2Alias) + .connect(l1GRTGatewayMockL2Alias) .finalizeInboundTransfer( - mockL1GRT.address, + l1GRTMock.address, tokenSender.address, rewardsManager.address, toGRT('10'), callHookData, ) await expect(tx).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) }) diff --git a/packages/contracts/test/l2/l2Staking.test.ts b/packages/contracts/test/unit/l2/l2Staking.test.ts similarity index 87% rename from packages/contracts/test/l2/l2Staking.test.ts rename to packages/contracts/test/unit/l2/l2Staking.test.ts index 890a697b3..9394a6116 100644 --- a/packages/contracts/test/l2/l2Staking.test.ts +++ b/packages/contracts/test/unit/l2/l2Staking.test.ts @@ -1,22 +1,23 @@ import hre from 'hardhat' import { expect } from 'chai' -import { ethers, ContractTransaction, BigNumber } from 'ethers' +import { BigNumber, ContractTransaction, ethers } from 'ethers' import { defaultAbiCoder, parseEther } from 'ethers/lib/utils' import { NetworkFixture } from '../lib/fixtures' -import { IL2Staking } from '../../build/types/IL2Staking' -import { L2GraphTokenGateway } from '../../build/types/L2GraphTokenGateway' -import { GraphToken } from '../../build/types/GraphToken' +import { IL2Staking } from '../../../build/types/IL2Staking' +import { L2GraphTokenGateway } from '../../../build/types/L2GraphTokenGateway' +import { GraphToken } from '../../../build/types/GraphToken' import { - GraphNetworkContracts, deriveChannelKey, + GraphNetworkContracts, helpers, randomHexBytes, toBN, toGRT, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { L1GNS, L1GraphTokenGateway, L1Staking } from '../../../build/types' const { AddressZero } = ethers.constants @@ -29,16 +30,16 @@ describe('L2Staking', () => { const graph = hre.graph() let me: SignerWithAddress let other: SignerWithAddress - let another: SignerWithAddress let governor: SignerWithAddress - let mockRouter: SignerWithAddress - let mockL1GRT: SignerWithAddress - let mockL1Gateway: SignerWithAddress - let mockL1GNS: SignerWithAddress - let mockL1Staking: SignerWithAddress + let fixture: NetworkFixture let fixtureContracts: GraphNetworkContracts + let l1MockContracts: GraphNetworkContracts + let l1GRTMock: GraphToken + let l1StakingMock: L1Staking + let l1GNSMock: L1GNS + let l1GRTGatewayMock: L1GraphTokenGateway let l2GraphTokenGateway: L2GraphTokenGateway let staking: IL2Staking let grt: GraphToken @@ -67,40 +68,45 @@ describe('L2Staking', () => { amount: BigNumber, callhookData: string, ): Promise { - const mockL1GatewayL2Alias = await helpers.getL2SignerFromL1(mockL1Gateway.address) + const mockL1GatewayL2Alias = await helpers.getL2SignerFromL1(l1GRTGatewayMock.address) // Eth for gas: await helpers.setBalance(await mockL1GatewayL2Alias.getAddress(), parseEther('1')) const tx = l2GraphTokenGateway .connect(mockL1GatewayL2Alias) - .finalizeInboundTransfer(mockL1GRT.address, from, to, amount, callhookData) + .finalizeInboundTransfer(l1GRTMock.address, from, to, amount, callhookData) return tx } before(async function () { - ;[me, other, another, mockRouter, mockL1GRT, mockL1Gateway, mockL1GNS, mockL1Staking] = - await graph.getTestAccounts() + [me, other] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) + + // Deploy L2 fixtureContracts = await fixture.load(governor, true) grt = fixtureContracts.GraphToken as GraphToken staking = fixtureContracts.Staking as IL2Staking - l2GraphTokenGateway = fixtureContracts.L2GraphTokenGateway as L2GraphTokenGateway + l2GraphTokenGateway = fixtureContracts.L2GraphTokenGateway + + // Deploy L1 mock + l1MockContracts = await fixture.loadMock(false) + l1GRTMock = l1MockContracts.GraphToken as GraphToken + l1StakingMock = l1MockContracts.L1Staking + l1GNSMock = l1MockContracts.L1GNS + l1GRTGatewayMock = l1MockContracts.L1GraphTokenGateway + + // Deploy L2 arbitrum bridge + await fixture.loadL2ArbitrumBridge(governor) + + // Configure L2 bridge + await fixture.configureL2Bridge(governor, fixtureContracts, l1MockContracts) await grt.connect(governor).mint(me.address, tokens1m) await grt.connect(me).approve(staking.address, tokens1m) await grt.connect(governor).mint(other.address, tokens1m) await grt.connect(other).approve(staking.address, tokens1m) - await fixture.configureL2Bridge( - governor, - fixtureContracts, - mockRouter.address, - mockL1GRT.address, - mockL1Gateway.address, - mockL1GNS.address, - mockL1Staking.address, - ) }) beforeEach(async function () { @@ -128,7 +134,7 @@ describe('L2Staking', () => { ['uint8', 'bytes'], [toBN(0), functionData], // code = 1 means RECEIVE_INDEXER_CODE ) - const tx = staking.connect(me).onTokenTransfer(mockL1GNS.address, tokens100k, callhookData) + const tx = staking.connect(me).onTokenTransfer(l1GNSMock.address, tokens100k, callhookData) await expect(tx).revertedWith('ONLY_GATEWAY') }) it('rejects calls if the L1 sender is not the L1Staking', async function () { @@ -150,7 +156,7 @@ describe('L2Staking', () => { [toBN(0), functionData], // code = 1 means RECEIVE_INDEXER_CODE ) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, tokens100k, callhookData, @@ -158,7 +164,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, tokens100k) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, tokens100k) await expect(tx).emit(staking, 'StakeDeposited').withArgs(me.address, tokens100k) expect(await staking.getIndexerStakedTokens(me.address)).to.equal(tokens100k) const delegationPool = await staking.delegationPools(me.address) @@ -173,13 +179,13 @@ describe('L2Staking', () => { [toBN(0), functionData], // code = 1 means RECEIVE_INDEXER_CODE ) await gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, tokens100k, callhookData, ) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, tokens100k, callhookData, @@ -187,7 +193,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, tokens100k) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, tokens100k) await expect(tx).emit(staking, 'StakeDeposited').withArgs(me.address, tokens100k) expect(await staking.getIndexerStakedTokens(me.address)).to.equal(tokens100k.add(tokens100k)) }) @@ -201,7 +207,7 @@ describe('L2Staking', () => { await staking.connect(me).stake(tokens100k) await staking.connect(me).setDelegationParameters(1000, 1000, 1000) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, tokens100k, callhookData, @@ -209,7 +215,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, tokens100k) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, tokens100k) await expect(tx).emit(staking, 'StakeDeposited').withArgs(me.address, tokens100k) expect(await staking.getIndexerStakedTokens(me.address)).to.equal(tokens100k.add(tokens100k)) const delegationPool = await staking.delegationPools(me.address) @@ -232,7 +238,7 @@ describe('L2Staking', () => { [toBN(1), functionData], // code = 1 means RECEIVE_DELEGATION_CODE ) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, tokens10k, callhookData, @@ -240,7 +246,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, tokens10k) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, tokens10k) const expectedShares = tokens10k await expect(tx) .emit(staking, 'StakeDelegated') @@ -262,7 +268,7 @@ describe('L2Staking', () => { [toBN(1), functionData], // code = 1 means RECEIVE_DELEGATION_CODE ) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, tokens10k, callhookData, @@ -270,7 +276,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, tokens10k) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, tokens10k) const expectedNewShares = tokens10k const expectedTotalShares = tokens10k.mul(2) await expect(tx) @@ -307,7 +313,7 @@ describe('L2Staking', () => { ) const delegatorGRTBalanceBefore = await grt.balanceOf(other.address) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, toBN(1), // Less than 1 share! callhookData, @@ -315,7 +321,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, toBN(1)) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, toBN(1)) const delegation = await staking.getDelegation(me.address, other.address) await expect(tx) .emit(staking, 'TransferredDelegationReturnedToDelegator') @@ -350,7 +356,7 @@ describe('L2Staking', () => { ) const delegatorGRTBalanceBefore = await grt.balanceOf(other.address) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, toGRT('0.1'), // Less than 1 GRT! callhookData, @@ -358,7 +364,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, toGRT('0.1')) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, toGRT('0.1')) const delegation = await staking.getDelegation(me.address, other.address) await expect(tx) .emit(staking, 'TransferredDelegationReturnedToDelegator') @@ -385,7 +391,7 @@ describe('L2Staking', () => { ) const delegatorGRTBalanceBefore = await grt.balanceOf(other.address) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, toGRT('0.1'), callhookData, @@ -393,7 +399,7 @@ describe('L2Staking', () => { await expect(tx) .emit(l2GraphTokenGateway, 'DepositFinalized') - .withArgs(mockL1GRT.address, mockL1Staking.address, staking.address, toGRT('0.1')) + .withArgs(l1GRTMock.address, l1StakingMock.address, staking.address, toGRT('0.1')) const delegation = await staking.getDelegation(me.address, other.address) await expect(tx) @@ -412,7 +418,7 @@ describe('L2Staking', () => { // code 2 does not exist: const callhookData = defaultAbiCoder.encode(['uint8', 'bytes'], [toBN(2), '0x12345678']) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, toGRT('1'), callhookData, @@ -424,7 +430,7 @@ describe('L2Staking', () => { // so we test it anyway to ensure it's a well-defined behavior. const callhookData = defaultAbiCoder.encode(['address', 'uint128'], [AddressZero, toBN(2)]) const tx = gatewayFinalizeTransfer( - mockL1Staking.address, + l1StakingMock.address, staking.address, toGRT('1'), callhookData, diff --git a/packages/contracts/test/unit/lib/fixtures.ts b/packages/contracts/test/unit/lib/fixtures.ts new file mode 100644 index 000000000..f65ed5230 --- /dev/null +++ b/packages/contracts/test/unit/lib/fixtures.ts @@ -0,0 +1,150 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { providers, Wallet } from 'ethers' + +import { Controller } from '../../../build/types/Controller' +import { DisputeManager } from '../../../build/types/DisputeManager' +import { EpochManager } from '../../../build/types/EpochManager' +import { GraphToken } from '../../../build/types/GraphToken' +import { Curation } from '../../../build/types/Curation' +import { L2Curation } from '../../../build/types/L2Curation' +import { L1GNS } from '../../../build/types/L1GNS' +import { L2GNS } from '../../../build/types/L2GNS' +import { IL1Staking } from '../../../build/types/IL1Staking' +import { IL2Staking } from '../../../build/types/IL2Staking' +import { RewardsManager } from '../../../build/types/RewardsManager' +import { ServiceRegistry } from '../../../build/types/ServiceRegistry' +import { GraphProxyAdmin } from '../../../build/types/GraphProxyAdmin' +import { L1GraphTokenGateway } from '../../../build/types/L1GraphTokenGateway' +import { BridgeEscrow } from '../../../build/types/BridgeEscrow' +import { L2GraphTokenGateway } from '../../../build/types/L2GraphTokenGateway' +import { L2GraphToken } from '../../../build/types/L2GraphToken' +import { LibExponential } from '../../../build/types/LibExponential' +import { + configureL1Bridge, + configureL2Bridge, + deployGraphNetwork, + deployMockGraphNetwork, + GraphNetworkContracts, + helpers, +} from '@graphprotocol/sdk' +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' + +export interface L1FixtureContracts { + controller: Controller + disputeManager: DisputeManager + epochManager: EpochManager + grt: GraphToken + curation: Curation + gns: L1GNS + staking: IL1Staking + libExponential: LibExponential + rewardsManager: RewardsManager + serviceRegistry: ServiceRegistry + proxyAdmin: GraphProxyAdmin + l1GraphTokenGateway: L1GraphTokenGateway + bridgeEscrow: BridgeEscrow +} + +export interface L2FixtureContracts { + controller: Controller + disputeManager: DisputeManager + epochManager: EpochManager + grt: L2GraphToken + curation: L2Curation + gns: L2GNS + staking: IL2Staking + libExponential: LibExponential + rewardsManager: RewardsManager + serviceRegistry: ServiceRegistry + proxyAdmin: GraphProxyAdmin + l2GraphTokenGateway: L2GraphTokenGateway +} + +export interface L2BridgeMocks { + l2GRTMock: Wallet + l2GRTGatewayMock: Wallet + l2GNSMock: Wallet + l2StakingMock: Wallet +} + +export class NetworkFixture { + lastSnapshot: any + constructor(public provider: providers.Provider) {} + + async load(deployer: SignerWithAddress, l2Deploy?: boolean): Promise { + return await deployGraphNetwork( + './addresses-local.json', + l2Deploy ? './config/graph.arbitrum-hardhat.yml' : './config/graph.hardhat.yml', + 1337, + deployer, + this.provider, + { + governor: deployer, + skipConfirmation: true, + forceDeploy: true, + l2Deploy: l2Deploy, + enableTxLogging: false, + }, + ) + } + + async loadMock(l2Deploy: boolean): Promise { + return await deployMockGraphNetwork(l2Deploy) + } + + async loadL1ArbitrumBridge(deployer: SignerWithAddress): Promise { + return await helpers.deployL1MockBridge( + deployer, + 'arbitrum-addresses-local.json', + this.provider, + ) + } + + async loadL2ArbitrumBridge(deployer: SignerWithAddress): Promise { + return await helpers.deployL2MockBridge( + deployer, + 'arbitrum-addresses-local.json', + this.provider, + ) + } + + async configureL1Bridge( + deployer: SignerWithAddress, + l1FixtureContracts: GraphNetworkContracts, + l2MockContracts: GraphNetworkContracts, + ): Promise { + await configureL1Bridge(l1FixtureContracts, deployer, { + l2GRTAddress: l2MockContracts.L2GraphToken.address, + l2GRTGatewayAddress: l2MockContracts.L2GraphTokenGateway.address, + l2GNSAddress: l2MockContracts.L2GNS.address, + l2StakingAddress: l2MockContracts.L2Staking.address, + arbAddressBookPath: './arbitrum-addresses-local.json', + chainId: 1337, + }) + await l1FixtureContracts.L1GraphTokenGateway.connect(deployer).setPaused(false) + } + + async configureL2Bridge( + deployer: SignerWithAddress, + l2FixtureContracts: GraphNetworkContracts, + l1MockContracts: GraphNetworkContracts, + ): Promise { + await configureL2Bridge(l2FixtureContracts, deployer, { + l1GRTAddress: l1MockContracts.GraphToken.address, + l1GRTGatewayAddress: l1MockContracts.L1GraphTokenGateway.address, + l1GNSAddress: l1MockContracts.L1GNS.address, + l1StakingAddress: l1MockContracts.L1Staking.address, + arbAddressBookPath: './arbitrum-addresses-local.json', + chainId: 412346, + }) + await l2FixtureContracts.L2GraphTokenGateway.connect(deployer).setPaused(false) + } + + async setUp(): Promise { + this.lastSnapshot = await helpers.takeSnapshot() + } + + async tearDown(): Promise { + await helpers.restoreSnapshot(this.lastSnapshot) + } +} diff --git a/packages/contracts/test/lib/gnsUtils.ts b/packages/contracts/test/unit/lib/gnsUtils.ts similarity index 95% rename from packages/contracts/test/lib/gnsUtils.ts rename to packages/contracts/test/unit/lib/gnsUtils.ts index f530c44dc..402e0325a 100644 --- a/packages/contracts/test/lib/gnsUtils.ts +++ b/packages/contracts/test/unit/lib/gnsUtils.ts @@ -1,13 +1,13 @@ import { BigNumber, ContractTransaction } from 'ethers' import { namehash } from 'ethers/lib/utils' -import { Curation } from '../../build/types/Curation' -import { L1GNS } from '../../build/types/L1GNS' -import { L2GNS } from '../../build/types/L2GNS' +import { Curation } from '../../../build/types/Curation' +import { L1GNS } from '../../../build/types/L1GNS' +import { L2GNS } from '../../../build/types/L2GNS' import { expect } from 'chai' -import { L2Curation } from '../../build/types/L2Curation' -import { GraphToken } from '../../build/types/GraphToken' -import { L2GraphToken } from '../../build/types/L2GraphToken' -import { PublishSubgraph, Subgraph, buildSubgraphId, toBN } from '@graphprotocol/sdk' +import { L2Curation } from '../../../build/types/L2Curation' +import { GraphToken } from '../../../build/types/GraphToken' +import { L2GraphToken } from '../../../build/types/L2GraphToken' +import { buildSubgraphId, PublishSubgraph, Subgraph, toBN } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' // Entities @@ -77,7 +77,8 @@ export const publishNewSubgraph = async ( const owner = await gns.ownerOf(subgraphID) expect(owner).eq(account.address) - return { ...subgraph, id: subgraphID } + // TODO: properly type this + return { ...subgraph, id: subgraphID } as unknown as Subgraph } export const publishNewVersion = async ( @@ -134,7 +135,7 @@ export const publishNewVersion = async ( // Only emits this event if there was actual signal to upgrade if (beforeSubgraph.nSignal.gt(0)) { - txResult + await txResult .emit(gns, 'SubgraphUpgraded') .withArgs(subgraphID, newVSignalEstimate, totalAdjustedUp, newSubgraph.subgraphDeploymentID) } diff --git a/packages/contracts/test/lib/graphTokenTests.ts b/packages/contracts/test/unit/lib/graphTokenTests.ts similarity index 95% rename from packages/contracts/test/lib/graphTokenTests.ts rename to packages/contracts/test/unit/lib/graphTokenTests.ts index 94f2f0fb0..77682ada9 100644 --- a/packages/contracts/test/lib/graphTokenTests.ts +++ b/packages/contracts/test/unit/lib/graphTokenTests.ts @@ -1,10 +1,10 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants, BigNumber, Signature, ethers, Wallet } from 'ethers' +import { BigNumber, constants, ethers, Signature, Wallet } from 'ethers' -import { L2GraphToken } from '../../build/types/L2GraphToken' -import { GraphToken } from '../../build/types/GraphToken' -import { toBN, toGRT, helpers, Permit, signPermit, GraphNetworkContracts } from '@graphprotocol/sdk' +import { L2GraphToken } from '../../../build/types/L2GraphToken' +import { GraphToken } from '../../../build/types/GraphToken' +import { GraphNetworkContracts, Permit, signPermit, toBN, toGRT } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { NetworkFixture } from './fixtures' @@ -72,7 +72,7 @@ export function grtTests(isL2: boolean): void { } before(async function () { - ;({ governor } = await graph.getNamedAccounts()) + ({ governor } = await graph.getNamedAccounts()) me = new ethers.Wallet(mePrivateKey, graph.provider) other = new ethers.Wallet(otherPrivateKey, graph.provider) @@ -176,7 +176,7 @@ export function grtTests(isL2: boolean): void { }) describe('mint', function () { - describe('mint', async function () { + describe('mint', function () { it('reject mint if not minter', async function () { const tx = grt.connect(me).mint(me.address, toGRT('100')) await expect(tx).revertedWith('Only minter can call') @@ -203,7 +203,7 @@ export function grtTests(isL2: boolean): void { expect(await grt.isMinter(me.address)).eq(true) }) - describe('mint', async function () { + describe('mint', function () { it('should mint', async function () { const beforeTokens = await grt.balanceOf(me.address) diff --git a/packages/contracts/test/payments/allocationExchange.test.ts b/packages/contracts/test/unit/payments/allocationExchange.test.ts similarity index 90% rename from packages/contracts/test/payments/allocationExchange.test.ts rename to packages/contracts/test/unit/payments/allocationExchange.test.ts index 16539ea7f..d5b0c69e7 100644 --- a/packages/contracts/test/payments/allocationExchange.test.ts +++ b/packages/contracts/test/unit/payments/allocationExchange.test.ts @@ -2,9 +2,9 @@ import hre from 'hardhat' import { expect } from 'chai' import { BigNumber, constants, Wallet } from 'ethers' -import { AllocationExchange } from '../../build/types/AllocationExchange' -import { GraphToken } from '../../build/types/GraphToken' -import { IStaking } from '../../build/types/IStaking' +import { AllocationExchange } from '../../../build/types/AllocationExchange' +import { GraphToken } from '../../../build/types/GraphToken' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' import { arrayify, joinSignature, SigningKey, solidityKeccak256 } from 'ethers/lib/utils' @@ -17,7 +17,7 @@ import { toGRT, } from '@graphprotocol/sdk' import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { EpochManager } from '../../build/types/EpochManager' +import { EpochManager } from '../../../build/types/EpochManager' const { AddressZero, MaxUint256 } = constants @@ -43,11 +43,11 @@ describe('AllocationExchange', () => { const graph = hre.graph() - async function createVoucher( + function createVoucher( allocationID: string, amount: BigNumber, signerKey: string, - ): Promise { + ): Voucher { const messageHash = solidityKeccak256(['address', 'uint256'], [allocationID, amount]) const messageHashBytes = arrayify(messageHash) const key = new SigningKey(signerKey) @@ -60,16 +60,16 @@ describe('AllocationExchange', () => { } before(async function () { - ;[indexer] = await graph.getTestAccounts() + [indexer] = await graph.getTestAccounts() ;({ governor, allocationExchangeOwner } = await graph.getNamedAccounts()) authority = Wallet.createRandom() fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) - allocationExchange = contracts.AllocationExchange as AllocationExchange + allocationExchange = contracts.AllocationExchange grt = contracts.GraphToken as GraphToken staking = contracts.Staking as IStaking - epochManager = contracts.EpochManager as EpochManager + epochManager = contracts.EpochManager // Give some funds to the indexer and approve staking contract to use funds on indexer behalf const indexerTokens = toGRT('100000') @@ -211,7 +211,7 @@ describe('AllocationExchange', () => { // Initiate a withdrawal const actualAmount = toGRT('2000') // <- withdraw amount - const voucher = await createVoucher(allocationID, actualAmount, authority.privateKey) + const voucher = createVoucher(allocationID, actualAmount, authority.privateKey) const tx = allocationExchange.connect(allocationExchangeOwner).redeem(voucher) await expect(tx) .emit(allocationExchange, 'AllocationRedeemed') @@ -233,7 +233,7 @@ describe('AllocationExchange', () => { // Initiate a withdrawal const actualAmount = toGRT('2000') // <- withdraw amount - const voucher = await createVoucher(allocationID, actualAmount, authority.privateKey) + const voucher = createVoucher(allocationID, actualAmount, authority.privateKey) // First redeem await allocationExchange.connect(allocationExchangeOwner).redeem(voucher) @@ -256,7 +256,7 @@ describe('AllocationExchange', () => { // Initiate a withdrawal const actualAmount = toGRT('2000') // <- withdraw amount - const voucher = await createVoucher(allocationID, actualAmount, authority.privateKey) + const voucher = createVoucher(allocationID, actualAmount, authority.privateKey) const tx = allocationExchange.connect(allocationExchangeOwner).redeem(voucher) await expect(tx).revertedWith('!collect') }) @@ -264,7 +264,7 @@ describe('AllocationExchange', () => { it('reject redeem voucher not signed by the authority', async function () { // Initiate a withdrawal const actualAmount = toGRT('2000') // <- withdraw amount - const voucher = await createVoucher( + const voucher = createVoucher( randomAddress(), actualAmount, Wallet.createRandom().privateKey, // <-- signed by anon @@ -276,14 +276,14 @@ describe('AllocationExchange', () => { it('reject redeem voucher with empty amount', async function () { // Initiate a withdrawal const actualAmount = toGRT('0') // <- withdraw amount - const voucher = await createVoucher(randomAddress(), actualAmount, authority.privateKey) + const voucher = createVoucher(randomAddress(), actualAmount, authority.privateKey) const tx = allocationExchange.connect(allocationExchangeOwner).redeem(voucher) await expect(tx).revertedWith('Exchange: zero tokens voucher') }) it('reject redeem voucher with invalid signature', async function () { const actualAmount = toGRT('2000') // <- withdraw amount - const voucher = await createVoucher(randomAddress(), actualAmount, authority.privateKey) + const voucher = createVoucher(randomAddress(), actualAmount, authority.privateKey) voucher.signature = '0x1234' const tx = allocationExchange.connect(allocationExchangeOwner).redeem(voucher) await expect(tx).revertedWith('Exchange: invalid signature') diff --git a/packages/contracts/test/rewards/rewards.test.ts b/packages/contracts/test/unit/rewards/rewards.test.ts similarity index 97% rename from packages/contracts/test/rewards/rewards.test.ts rename to packages/contracts/test/unit/rewards/rewards.test.ts index 861249342..089ab3801 100644 --- a/packages/contracts/test/rewards/rewards.test.ts +++ b/packages/contracts/test/unit/rewards/rewards.test.ts @@ -1,24 +1,24 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants, BigNumber } from 'ethers' +import { BigNumber, constants } from 'ethers' import { BigNumber as BN } from 'bignumber.js' import { NetworkFixture } from '../lib/fixtures' -import { Curation } from '../../build/types/Curation' -import { EpochManager } from '../../build/types/EpochManager' -import { GraphToken } from '../../build/types/GraphToken' -import { RewardsManager } from '../../build/types/RewardsManager' -import { IStaking } from '../../build/types/IStaking' +import { Curation } from '../../../build/types/Curation' +import { EpochManager } from '../../../build/types/EpochManager' +import { GraphToken } from '../../../build/types/GraphToken' +import { RewardsManager } from '../../../build/types/RewardsManager' +import { IStaking } from '../../../build/types/IStaking' import { - helpers, + deriveChannelKey, formatGRT, + GraphNetworkContracts, + helpers, randomHexBytes, toBN, toGRT, - deriveChannelKey, - GraphNetworkContracts, } from '@graphprotocol/sdk' import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' @@ -102,7 +102,7 @@ describe('Rewards', () => { return this.accruedByElapsed(nBlocks) } - async accruedByElapsed(nBlocks: BigNumber | number) { + accruedByElapsed(nBlocks: BigNumber | number) { const n = getRewardsPerSignal( new BN(ISSUANCE_PER_BLOCK.toString()), new BN(nBlocks.toString()), @@ -133,17 +133,17 @@ describe('Rewards', () => { } before(async function () { - ;[delegator, curator1, curator2, indexer1, indexer2, oracle, assetHolder] = - await graph.getTestAccounts() + [delegator, curator1, curator2, indexer1, indexer2, oracle, assetHolder] + = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) grt = contracts.GraphToken as GraphToken curation = contracts.Curation as Curation - epochManager = contracts.EpochManager as EpochManager + epochManager = contracts.EpochManager staking = contracts.Staking as IStaking - rewardsManager = contracts.RewardsManager as RewardsManager + rewardsManager = contracts.RewardsManager // 200 GRT per block await rewardsManager.connect(governor).setIssuancePerBlock(ISSUANCE_PER_BLOCK) @@ -216,7 +216,7 @@ describe('Rewards', () => { }) }) - context('issuing rewards', async function () { + context('issuing rewards', function () { beforeEach(async function () { // 5% minute rate (4 blocks) await rewardsManager.connect(governor).setIssuancePerBlock(ISSUANCE_PER_BLOCK) @@ -312,8 +312,8 @@ describe('Rewards', () => { await tracker2.snapshot() // Calculate rewards - const rewardsPerSignal1 = await tracker1.accumulated - const rewardsPerSignal2 = await tracker2.accumulated + const rewardsPerSignal1 = tracker1.accumulated + const rewardsPerSignal2 = tracker2.accumulated const expectedRewardsSG1 = rewardsPerSignal1.mul(signalled1).div(WeiPerEther) const expectedRewardsSG2 = rewardsPerSignal2.mul(signalled2).div(WeiPerEther) @@ -979,7 +979,7 @@ describe('Rewards', () => { it('collect query fees with two subgraphs and one allocation', async function () { async function getRewardsAccrual(subgraphs) { const [sg1, sg2] = await Promise.all( - subgraphs.map((sg) => rewardsManager.getAccRewardsForSubgraph(sg)), + subgraphs.map(sg => rewardsManager.getAccRewardsForSubgraph(sg)), ) return { sg1, @@ -1001,14 +1001,14 @@ describe('Rewards', () => { } // snapshot block before any accrual (we substract 1 because accrual starts after the first mint happens) - const b1 = await epochManager.blockNum().then((x) => x.toNumber() - 1) + const b1 = await epochManager.blockNum().then(x => x.toNumber() - 1) // allocate const tokensToAllocate = toGRT('12500') await staking .connect(indexer1) .multicall([ - await staking.populateTransaction.stake(tokensToAllocate).then((tx) => tx.data), + await staking.populateTransaction.stake(tokensToAllocate).then(tx => tx.data), await staking.populateTransaction .allocateFrom( indexer1.address, @@ -1018,7 +1018,7 @@ describe('Rewards', () => { metadata, await channelKey1.generateProof(indexer1.address), ) - .then((tx) => tx.data), + .then(tx => tx.data), ]) // move time fwd @@ -1032,7 +1032,7 @@ describe('Rewards', () => { await helpers.mine() const accrual = await getRewardsAccrual(subgraphs) - const b2 = await epochManager.blockNum().then((x) => x.toNumber()) + const b2 = await epochManager.blockNum().then(x => x.toNumber()) // round comparison because there is a small precision error due to dividing and accrual per signal expect(toRound(accrual.all)).eq(toRound(ISSUANCE_PER_BLOCK.mul(b2 - b1))) diff --git a/packages/contracts/test/rewards/subgraphAvailability.test.ts b/packages/contracts/test/unit/rewards/subgraphAvailability.test.ts similarity index 98% rename from packages/contracts/test/rewards/subgraphAvailability.test.ts rename to packages/contracts/test/unit/rewards/subgraphAvailability.test.ts index 1f04a3bbc..f86105a03 100644 --- a/packages/contracts/test/rewards/subgraphAvailability.test.ts +++ b/packages/contracts/test/unit/rewards/subgraphAvailability.test.ts @@ -12,11 +12,11 @@ import { IRewardsManager } from '../../build/types/IRewardsManager' import { NetworkFixture } from '../lib/fixtures' import { + deploy, + DeployType, GraphNetworkContracts, randomAddress, randomHexBytes, - deploy, - DeployType, } from '@graphprotocol/sdk' const { AddressZero } = constants @@ -49,8 +49,8 @@ describe('SubgraphAvailabilityManager', () => { const subgraphDeploymentID3 = randomHexBytes() before(async () => { - ;[me, oracleOne, oracleTwo, oracleThree, oracleFour, oracleFive, newOracle] = - await graph.getTestAccounts() + [me, oracleOne, oracleTwo, oracleThree, oracleFour, oracleFive, newOracle] + = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) oracles = [ @@ -85,7 +85,7 @@ describe('SubgraphAvailabilityManager', () => { }) describe('deployment', () => { - it('should deploy', async () => { + it('should deploy', function () { expect(subgraphAvailabilityManager.address).to.be.properAddress }) @@ -182,7 +182,7 @@ describe('SubgraphAvailabilityManager', () => { }) }) - describe('set vote limit', async () => { + describe('set vote limit', function () { it('sets voteTimeLimit successfully', async () => { const newVoteTimeLimit = 10 await expect(subgraphAvailabilityManager.connect(governor).setVoteTimeLimit(newVoteTimeLimit)) @@ -229,7 +229,7 @@ describe('SubgraphAvailabilityManager', () => { }) }) - describe('voting', async () => { + describe('voting', function () { it('votes denied successfully', async () => { const denied = true const tx = await subgraphAvailabilityManager @@ -356,7 +356,7 @@ describe('SubgraphAvailabilityManager', () => { }) }) - describe('vote many', async () => { + describe('vote many', function () { it('votes many successfully', async () => { const subgraphs = [subgraphDeploymentID1, subgraphDeploymentID2, subgraphDeploymentID3] const denied = [true, false, true] diff --git a/packages/contracts/test/serviceRegisty.test.ts b/packages/contracts/test/unit/serviceRegisty.test.ts similarity index 94% rename from packages/contracts/test/serviceRegisty.test.ts rename to packages/contracts/test/unit/serviceRegisty.test.ts index b053486eb..d84b4aa88 100644 --- a/packages/contracts/test/serviceRegisty.test.ts +++ b/packages/contracts/test/unit/serviceRegisty.test.ts @@ -1,8 +1,8 @@ import hre from 'hardhat' import { expect } from 'chai' -import { ServiceRegistry } from '../build/types/ServiceRegistry' -import { IStaking } from '../build/types/IStaking' +import { ServiceRegistry } from '../../build/types/ServiceRegistry' +import { IStaking } from '../../build/types/IStaking' import { NetworkFixture } from './lib/fixtures' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' @@ -34,11 +34,11 @@ describe('ServiceRegistry', () => { } before(async function () { - ;[governor, indexer, operator] = await graph.getTestAccounts() + [governor, indexer, operator] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) - serviceRegistry = contracts.ServiceRegistry as ServiceRegistry + serviceRegistry = contracts.ServiceRegistry staking = contracts.Staking as IStaking }) diff --git a/packages/contracts/test/staking/allocation.test.ts b/packages/contracts/test/unit/staking/allocation.test.ts similarity index 97% rename from packages/contracts/test/staking/allocation.test.ts rename to packages/contracts/test/unit/staking/allocation.test.ts index c4a104312..92afedca4 100644 --- a/packages/contracts/test/staking/allocation.test.ts +++ b/packages/contracts/test/unit/staking/allocation.test.ts @@ -1,17 +1,17 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants, BigNumber, PopulatedTransaction, Contract } from 'ethers' +import { BigNumber, constants, Contract, PopulatedTransaction } from 'ethers' -import { Curation } from '../../build/types/Curation' -import { EpochManager } from '../../build/types/EpochManager' -import { GraphToken } from '../../build/types/GraphToken' -import { IStaking } from '../../build/types/IStaking' -import { LibExponential } from '../../build/types/LibExponential' +import { Curation } from '../../../build/types/Curation' +import { EpochManager } from '../../../build/types/EpochManager' +import { GraphToken } from '../../../build/types/GraphToken' +import { IStaking } from '../../../build/types/IStaking' +import { LibExponential } from '../../../build/types/LibExponential' import { NetworkFixture } from '../lib/fixtures' import { - GraphNetworkContracts, deriveChannelKey, + GraphNetworkContracts, helpers, isGraphL1ChainId, randomHexBytes, @@ -84,7 +84,6 @@ describe('Staking:Allocation', () => { let governor: SignerWithAddress let indexer: SignerWithAddress let delegator: SignerWithAddress - let slasher: SignerWithAddress let assetHolder: SignerWithAddress let fixture: NetworkFixture @@ -171,7 +170,7 @@ describe('Staking:Allocation', () => { allocationID?: string expectEvent?: boolean } = {}, - ): Promise<{ queryRebates: BigNumber; queryFeesBurnt: BigNumber }> => { + ): Promise<{ queryRebates: BigNumber, queryFeesBurnt: BigNumber }> => { const expectEvent = options.expectEvent ?? true const alloID = options.allocationID ?? allocationID const alloStateBefore = await staking.getAllocationState(alloID) @@ -201,8 +200,8 @@ describe('Staking:Allocation', () => { const queryFees = tokensToCollect.sub(protocolFees).sub(curationFees) - const [alphaNumerator, alphaDenominator, lambdaNumerator, lambdaDenominator] = - await Promise.all([ + const [alphaNumerator, alphaDenominator, lambdaNumerator, lambdaDenominator] + = await Promise.all([ staking.alphaNumerator(), staking.alphaDenominator(), staking.lambdaNumerator(), @@ -367,13 +366,13 @@ describe('Staking:Allocation', () => { // -- Tests -- before(async function () { - ;[me, indexer, delegator, slasher, assetHolder] = await graph.getTestAccounts() + [me, indexer, delegator, assetHolder] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) curation = contracts.Curation as Curation - epochManager = contracts.EpochManager as EpochManager + epochManager = contracts.EpochManager grt = contracts.GraphToken as GraphToken staking = contracts.Staking as IStaking @@ -624,7 +623,7 @@ describe('Staking:Allocation', () => { `> with ${toPercentage(params.curationPercentage)}% curationFees, ${toPercentage( params.protocolPercentage, )}% protocolTax and ${toPercentage(params.queryFeeCut)}% queryFeeCut`, - async function () { + function () { beforeEach(async function () { // Set a protocol fee percentage await staking.connect(governor).setProtocolPercentage(params.protocolPercentage) @@ -836,7 +835,7 @@ describe('Staking:Allocation', () => { // Update rebate parameters, α = 0, λ = 1 await staking.connect(governor).setRebateParameters(0, 1, 1, 1) - // Succesive collections + // Successive collections // Indexer gets 100% of the query fees // Parameters changed so now they are under-rebated and should get more than the available amount but we cap it // Distributed amount will never catch up due to the initial collection which was less than 100% @@ -860,7 +859,7 @@ describe('Staking:Allocation', () => { }) for (const tokensToAllocate of [toBN(100), toBN(0)]) { - context(`> with ${tokensToAllocate} allocated tokens`, async function () { + context(`> with ${tokensToAllocate.toString()} allocated tokens`, function () { beforeEach(async function () { // Advance to next epoch to avoid creating the allocation // right at the epoch boundary, which would mess up the tests. @@ -994,7 +993,7 @@ describe('Staking:Allocation', () => { ].map(({ allocationID, poi }) => staking.connect(indexer).populateTransaction.closeAllocation(allocationID, poi), ), - ).then((e) => e.map((e: PopulatedTransaction) => e.data)) + ).then(e => e.map((e: PopulatedTransaction) => e.data)) await staking.connect(indexer).multicall(requests) }) }) @@ -1029,7 +1028,7 @@ describe('Staking:Allocation', () => { metadata, await newChannelKey.generateProof(indexer.address), ), - ]).then((e) => e.map((e: PopulatedTransaction) => e.data)) + ]).then(e => e.map((e: PopulatedTransaction) => e.data)) await staking.connect(indexer).multicall(requests) }) }) diff --git a/packages/contracts/test/staking/configuration.test.ts b/packages/contracts/test/unit/staking/configuration.test.ts similarity index 95% rename from packages/contracts/test/staking/configuration.test.ts rename to packages/contracts/test/unit/staking/configuration.test.ts index d9e848f41..44f9d5bd0 100644 --- a/packages/contracts/test/staking/configuration.test.ts +++ b/packages/contracts/test/unit/staking/configuration.test.ts @@ -3,11 +3,11 @@ import { expect } from 'chai' import { ethers } from 'hardhat' import { constants } from 'ethers' -import { IStaking } from '../../build/types/IStaking' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' -import { GraphProxyAdmin } from '../../build/types/GraphProxyAdmin' -import { DeployType, GraphNetworkContracts, deploy, toBN, toGRT } from '@graphprotocol/sdk' +import { GraphProxyAdmin } from '../../../build/types/GraphProxyAdmin' +import { deploy, DeployType, GraphNetworkContracts, toBN, toGRT } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' const { AddressZero } = constants @@ -16,12 +16,10 @@ const MAX_PPM = toBN('1000000') describe('Staking:Config', () => { const graph = hre.graph() - const defaults = graph.graphConfig.defaults let me: SignerWithAddress let other: SignerWithAddress let governor: SignerWithAddress - let slasher: SignerWithAddress let fixture: NetworkFixture @@ -30,13 +28,13 @@ describe('Staking:Config', () => { let proxyAdmin: GraphProxyAdmin before(async function () { - ;[me, other, slasher] = await graph.getTestAccounts() + [me, other] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) staking = contracts.Staking as IStaking - proxyAdmin = contracts.GraphProxyAdmin as GraphProxyAdmin + proxyAdmin = contracts.GraphProxyAdmin }) beforeEach(async function () { diff --git a/packages/contracts/test/staking/delegation.test.ts b/packages/contracts/test/unit/staking/delegation.test.ts similarity index 98% rename from packages/contracts/test/staking/delegation.test.ts rename to packages/contracts/test/unit/staking/delegation.test.ts index 3273ff52d..f866be9c6 100644 --- a/packages/contracts/test/staking/delegation.test.ts +++ b/packages/contracts/test/unit/staking/delegation.test.ts @@ -1,15 +1,15 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants, BigNumber } from 'ethers' +import { BigNumber, constants } from 'ethers' -import { EpochManager } from '../../build/types/EpochManager' -import { GraphToken } from '../../build/types/GraphToken' -import { IStaking } from '../../build/types/IStaking' +import { EpochManager } from '../../../build/types/EpochManager' +import { GraphToken } from '../../../build/types/GraphToken' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' import { - GraphNetworkContracts, deriveChannelKey, + GraphNetworkContracts, helpers, randomHexBytes, toBN, @@ -183,13 +183,13 @@ describe('Staking::Delegation', () => { } before(async function () { - ;[me, delegator, delegator2, governor, indexer, indexer2, assetHolder] = - await graph.getTestAccounts() + [me, delegator, delegator2, governor, indexer, indexer2, assetHolder] + = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) - epochManager = contracts.EpochManager as EpochManager + epochManager = contracts.EpochManager grt = contracts.GraphToken as GraphToken staking = contracts.Staking as IStaking diff --git a/packages/contracts/test/staking/l2Transfer.test.ts b/packages/contracts/test/unit/staking/l2Transfer.test.ts similarity index 94% rename from packages/contracts/test/staking/l2Transfer.test.ts rename to packages/contracts/test/unit/staking/l2Transfer.test.ts index a6743bffc..31be6c044 100644 --- a/packages/contracts/test/staking/l2Transfer.test.ts +++ b/packages/contracts/test/unit/staking/l2Transfer.test.ts @@ -1,55 +1,51 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants, BigNumber } from 'ethers' +import { BigNumber, constants } from 'ethers' import { defaultAbiCoder, parseEther } from 'ethers/lib/utils' -import { GraphToken } from '../../build/types/GraphToken' -import { IL1Staking } from '../../build/types/IL1Staking' -import { IController } from '../../build/types/IController' -import { L1GraphTokenGateway } from '../../build/types/L1GraphTokenGateway' -import { L1GraphTokenLockTransferToolMock } from '../../build/types/L1GraphTokenLockTransferToolMock' -import { L1GraphTokenLockTransferToolBadMock } from '../../build/types/L1GraphTokenLockTransferToolBadMock' +import { GraphToken } from '../../../build/types/GraphToken' +import { IL1Staking } from '../../../build/types/IL1Staking' +import { IController } from '../../../build/types/IController' +import { L1GraphTokenGateway } from '../../../build/types/L1GraphTokenGateway' +import { L1GraphTokenLockTransferToolMock } from '../../../build/types/L1GraphTokenLockTransferToolMock' +import { L1GraphTokenLockTransferToolBadMock } from '../../../build/types/L1GraphTokenLockTransferToolBadMock' -import { ArbitrumL1Mocks, NetworkFixture } from '../lib/fixtures' +import { NetworkFixture } from '../lib/fixtures' import { - DeployType, - GraphNetworkContracts, deploy, + DeployType, deriveChannelKey, + GraphNetworkContracts, helpers, randomHexBytes, toBN, toGRT, } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { IStaking } from '../../build/types/IStaking' +import { L2GraphTokenGateway, L2Staking } from '../../../build/types' const { AddressZero } = constants describe('L1Staking:L2Transfer', () => { const graph = hre.graph() - let me: SignerWithAddress let governor: SignerWithAddress let indexer: SignerWithAddress - let slasher: SignerWithAddress let l2Indexer: SignerWithAddress let delegator: SignerWithAddress let l2Delegator: SignerWithAddress - let mockRouter: SignerWithAddress - let mockL2GRT: SignerWithAddress - let mockL2Gateway: SignerWithAddress - let mockL2GNS: SignerWithAddress - let mockL2Staking: SignerWithAddress let fixture: NetworkFixture let fixtureContracts: GraphNetworkContracts + let l2MockContracts: GraphNetworkContracts + + let l2StakingMock: L2Staking + let l2GRTGatewayMock: L2GraphTokenGateway let grt: GraphToken let staking: IL1Staking let controller: IController let l1GraphTokenGateway: L1GraphTokenGateway - let arbitrumMocks: ArbitrumL1Mocks let l1GraphTokenLockTransferTool: L1GraphTokenLockTransferToolMock let l1GraphTokenLockTransferToolBad: L1GraphTokenLockTransferToolBadMock @@ -83,41 +79,28 @@ describe('L1Staking:L2Transfer', () => { } before(async function () { - ;[ - me, - indexer, - slasher, - delegator, - l2Indexer, - mockRouter, - mockL2GRT, - mockL2Gateway, - mockL2GNS, - mockL2Staking, - l2Delegator, - ] = await graph.getTestAccounts() + [indexer, delegator, l2Indexer, l2Delegator] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) + + // Deploy L1 fixtureContracts = await fixture.load(governor) grt = fixtureContracts.GraphToken as GraphToken staking = fixtureContracts.L1Staking as unknown as IL1Staking - l1GraphTokenGateway = fixtureContracts.L1GraphTokenGateway as L1GraphTokenGateway + l1GraphTokenGateway = fixtureContracts.L1GraphTokenGateway controller = fixtureContracts.Controller as IController - // Dummy code on the mock router so that it appears as a contract - await helpers.setCode(mockRouter.address, '0x1234') - arbitrumMocks = await fixture.loadArbitrumL1Mocks(governor) - await fixture.configureL1Bridge( - governor, - arbitrumMocks, - fixtureContracts, - mockRouter.address, - mockL2GRT.address, - mockL2Gateway.address, - mockL2GNS.address, - mockL2Staking.address, - ) + // Deploy L1 arbitrum bridge + await fixture.loadL1ArbitrumBridge(governor) + + // Deploy L2 mock + l2MockContracts = await fixture.loadMock(true) + l2StakingMock = l2MockContracts.L2Staking + l2GRTGatewayMock = l2MockContracts.L2GraphTokenGateway + + // Configure graph bridge + await fixture.configureL1Bridge(governor, fixtureContracts, l2MockContracts) l1GraphTokenLockTransferTool = ( await deploy(DeployType.Deploy, governor, { @@ -201,14 +184,14 @@ describe('L1Staking:L2Transfer', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, staking.address, - mockL2Staking.address, + l2StakingMock.address, amountToSend, expectedCallhookData, ) await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(staking.address, mockL2Gateway.address, toBN(expectedSeqNum), expectedL2Data) + .withArgs(staking.address, l2GRTGatewayMock.address, toBN(expectedSeqNum), expectedL2Data) } beforeEach(async function () { @@ -449,14 +432,14 @@ describe('L1Staking:L2Transfer', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, staking.address, - mockL2Staking.address, + l2StakingMock.address, amountToSend, expectedCallhookData, ) await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(staking.address, mockL2Gateway.address, toBN(1), expectedL2Data) + .withArgs(staking.address, l2GRTGatewayMock.address, toBN(1), expectedL2Data) expect(await graph.provider.getBalance(l1GraphTokenLockTransferTool.address)).to.equal( oldTransferToolEthBalance.sub(maxSubmissionCost).sub(gasPriceBid.mul(maxGas)), ) @@ -734,7 +717,7 @@ describe('L1Staking:L2Transfer', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, staking.address, - mockL2Staking.address, + l2StakingMock.address, actualDelegation, expectedCallhookData, ) @@ -754,7 +737,7 @@ describe('L1Staking:L2Transfer', () => { // seqNum is 2 because the first bridge call was in transferStakeToL2 await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(staking.address, mockL2Gateway.address, toBN(2), expectedL2Data) + .withArgs(staking.address, l2GRTGatewayMock.address, toBN(2), expectedL2Data) await expect(tx) .emit(staking, 'DelegationTransferredToL2') .withArgs( @@ -936,7 +919,7 @@ describe('L1Staking:L2Transfer', () => { const expectedL2Data = await l1GraphTokenGateway.getOutboundCalldata( grt.address, staking.address, - mockL2Staking.address, + l2StakingMock.address, actualDelegation, expectedCallhookData, ) @@ -955,7 +938,7 @@ describe('L1Staking:L2Transfer', () => { // seqNum is 2 because the first bridge call was in transferStakeToL2 await expect(tx) .emit(l1GraphTokenGateway, 'TxToL2') - .withArgs(staking.address, mockL2Gateway.address, toBN(2), expectedL2Data) + .withArgs(staking.address, l2GRTGatewayMock.address, toBN(2), expectedL2Data) await expect(tx) .emit(staking, 'DelegationTransferredToL2') .withArgs( diff --git a/packages/contracts/test/staking/rebate.test.ts b/packages/contracts/test/unit/staking/rebate.test.ts similarity index 95% rename from packages/contracts/test/staking/rebate.test.ts rename to packages/contracts/test/unit/staking/rebate.test.ts index ba9dd3c89..7eb989fdc 100644 --- a/packages/contracts/test/staking/rebate.test.ts +++ b/packages/contracts/test/unit/staking/rebate.test.ts @@ -2,9 +2,9 @@ import hre from 'hardhat' import { expect } from 'chai' import { BigNumber, Contract } from 'ethers' -import { LibExponential } from '../../build/types/LibExponential' +import { LibExponential } from '../../../build/types/LibExponential' -import { formatGRT, helpers, isGraphL1ChainId, toGRT } from '@graphprotocol/sdk' +import { formatGRT, isGraphL1ChainId, toGRT } from '@graphprotocol/sdk' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { NetworkFixture } from '../lib/fixtures' @@ -94,6 +94,7 @@ export function exponentialRebates( } const exponent = (lambda * stake) / fees + // eslint-disable-next-line no-secrets/no-secrets // LibExponential.MAX_EXPONENT = 15 if (exponent > 15) { return fees @@ -163,7 +164,7 @@ describe('Staking:rebates', () => { } } - async function testRebateParameters(fn, testCases) { + function testRebateParameters(fn, testCases) { // *** Exponential rebates *** // Typical alpha and lambda it('alpha 1 - lambda 0.6', async function () { @@ -209,7 +210,7 @@ describe('Staking:rebates', () => { } before(async function () { - ;({ governor } = await graph.getNamedAccounts()) + ({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) await fixture.load(governor) diff --git a/packages/contracts/test/staking/staking.test.ts b/packages/contracts/test/unit/staking/staking.test.ts similarity index 92% rename from packages/contracts/test/staking/staking.test.ts rename to packages/contracts/test/unit/staking/staking.test.ts index d1e9a2c00..6fe5fdcb0 100644 --- a/packages/contracts/test/staking/staking.test.ts +++ b/packages/contracts/test/unit/staking/staking.test.ts @@ -1,15 +1,15 @@ import hre from 'hardhat' import { expect } from 'chai' -import { constants, BigNumber, Event } from 'ethers' +import { BigNumber, constants, Event } from 'ethers' -import { GraphToken } from '../../build/types/GraphToken' -import { IStaking } from '../../build/types/IStaking' +import { GraphToken } from '../../../build/types/GraphToken' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' import { - GraphNetworkContracts, deriveChannelKey, + GraphNetworkContracts, helpers, randomHexBytes, toBN, @@ -84,7 +84,7 @@ describe('Staking:Stakes', () => { } before(async function () { - ;[me, indexer, slasher, fisherman] = await graph.getTestAccounts() + [me, indexer, slasher, fisherman] = await graph.getTestAccounts() ;({ governor } = await graph.getNamedAccounts()) fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) @@ -239,6 +239,36 @@ describe('Staking:Stakes', () => { expect(afterIndexerStake.tokensLockedUntil).eq(expectedLockedUntil) }) + it('should always increase the thawing period on subsequent unstakes', async function () { + const tokensToUnstake = toGRT('10') + const tokensToUnstakeSecondTime = toGRT('0.000001') + + // Unstake (1) + const tx1 = await staking.connect(indexer).unstake(tokensToUnstake) + const receipt1 = await tx1.wait() + const event1: Event = receipt1.events.pop() + const tokensLockedUntil1 = event1.args['until'] + + // Move forward before the tokens are unlocked for withdrawal + await helpers.mineUpTo(tokensLockedUntil1.sub(5)) + + // Ensure at least 1 block is added (i.e. the weighted average rounds up) + const expectedLockedUntil = tokensLockedUntil1.add(1) + + // Unstake (2) + const tx2 = await staking.connect(indexer).unstake(tokensToUnstakeSecondTime) + const receipt2 = await tx2.wait() + + // Verify events + const event2: Event = receipt2.events.pop() + expect(event2.args['until']).eq(expectedLockedUntil) + + // Verify state + const afterIndexerStake = await staking.stakes(indexer.address) + expect(afterIndexerStake.tokensLocked).eq(tokensToUnstake.add(tokensToUnstakeSecondTime)) // we unstaked two times + expect(afterIndexerStake.tokensLockedUntil).eq(expectedLockedUntil) + }) + it('should unstake and withdraw if some tokens are unthawed', async function () { const tokensToUnstake = toGRT('10') const thawingPeriod = toBN(await staking.thawingPeriod()) diff --git a/packages/contracts/test/upgrade/admin.test.ts b/packages/contracts/test/unit/upgrade/admin.test.ts similarity index 88% rename from packages/contracts/test/upgrade/admin.test.ts rename to packages/contracts/test/unit/upgrade/admin.test.ts index 3cee40a6d..f18cfa0fa 100644 --- a/packages/contracts/test/upgrade/admin.test.ts +++ b/packages/contracts/test/unit/upgrade/admin.test.ts @@ -2,15 +2,15 @@ import { expect } from 'chai' import hre from 'hardhat' import '@nomiclabs/hardhat-ethers' -import { GraphProxy } from '../../build/types/GraphProxy' -import { Curation } from '../../build/types/Curation' -import { GraphProxyAdmin } from '../../build/types/GraphProxyAdmin' -import { IStaking } from '../../build/types/IStaking' +import { GraphProxy } from '../../../build/types/GraphProxy' +import { Curation } from '../../../build/types/Curation' +import { GraphProxyAdmin } from '../../../build/types/GraphProxyAdmin' +import { IStaking } from '../../../build/types/IStaking' import { NetworkFixture } from '../lib/fixtures' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { DeployType, GraphNetworkContracts, deploy, loadContractAt } from '@graphprotocol/sdk' +import { deploy, DeployType, GraphNetworkContracts, loadContractAt } from '@graphprotocol/sdk' const { ethers } = hre const { AddressZero } = ethers.constants @@ -29,12 +29,12 @@ describe('Upgrades', () => { let stakingProxy: GraphProxy before(async function () { - ;[me, governor] = await graph.getTestAccounts() + [me, governor] = await graph.getTestAccounts() fixture = new NetworkFixture(graph.provider) contracts = await fixture.load(governor) staking = contracts.Staking as IStaking - proxyAdmin = contracts.GraphProxyAdmin as GraphProxyAdmin + proxyAdmin = contracts.GraphProxyAdmin curation = contracts.Curation as Curation stakingProxy = loadContractAt('GraphProxy', staking.address, undefined, governor) as GraphProxy @@ -59,7 +59,7 @@ describe('Upgrades', () => { it('reject get admin from other than the ProxyAdmin', async function () { await expect(stakingProxy.connect(governor).admin()).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) }) @@ -72,7 +72,7 @@ describe('Upgrades', () => { it('reject get implementation from other than the ProxyAdmin', async function () { await expect(stakingProxy.implementation()).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) }) @@ -87,7 +87,7 @@ describe('Upgrades', () => { it('reject get pending implementation from other than the ProxyAdmin', async function () { await expect(stakingProxy.connect(governor).pendingImplementation()).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) }) @@ -134,7 +134,7 @@ describe('Upgrades', () => { // Due to the transparent proxy we should not be able to upgrade from other than the proxy admin const tx = stakingProxy.connect(governor).upgradeTo(newImplementationAddress) await expect(tx).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) }) @@ -144,7 +144,7 @@ describe('Upgrades', () => { // Due to the transparent proxy we should not be able to accept upgrades from other than the proxy admin const tx = stakingProxy.connect(governor).acceptUpgrade() await expect(tx).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) }) @@ -185,7 +185,7 @@ describe('Upgrades', () => { .connect(governor) .changeProxyAdmin(staking.address, otherProxyAdmin.address) await expect(tx).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) @@ -202,7 +202,7 @@ describe('Upgrades', () => { // Due to the transparent proxy we should not be able to set admin from other than the proxy admin const tx = stakingProxy.connect(governor).setAdmin(me.address) await expect(tx).revertedWith( - "function selector was not recognized and there's no fallback function", + 'function selector was not recognized and there\'s no fallback function', ) }) }) diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json index bc81ee12d..a12f7de23 100644 --- a/packages/contracts/tsconfig.json +++ b/packages/contracts/tsconfig.json @@ -9,11 +9,14 @@ "esModuleInterop": true }, "include": [ - "hardhat.config.ts", - "index.d.ts", - "scripts/**/*.ts", - "test/**/*.ts", - "tasks/**/*.ts", - "e2e/**/*.ts" + ".solcover.js", + "truffle.js", + "eslint.config.js", + "prettier.config.js", + "hardhat.config.ts", + "index.d.ts", + "scripts/**/*.ts", + "test/**/*.ts", + "tasks/**/*.ts" ] } diff --git a/packages/eslint-graph-config/.gitignore b/packages/eslint-graph-config/.gitignore new file mode 100644 index 000000000..945ce43a9 --- /dev/null +++ b/packages/eslint-graph-config/.gitignore @@ -0,0 +1 @@ +index.js \ No newline at end of file diff --git a/packages/eslint-graph-config/README.md b/packages/eslint-graph-config/README.md new file mode 100644 index 000000000..3e0a41cff --- /dev/null +++ b/packages/eslint-graph-config/README.md @@ -0,0 +1,76 @@ +# eslint-graph-config + +This repository contains shared linting and formatting rules for TypeScript projects. + +## Installation + +```bash +yarn add --dev eslint eslint-graph-config +``` + +For projects on this monorepo, you can use the following command to install the package: + +```bash +yarn add --dev eslint eslint-graph-config@workspace:^x.y.z +``` + +To enable the rules, you need to create an `eslint.config.js` file in the root of your project with the following content: + +```javascript +const config = require('eslint-graph-config') +module.exports = config.default + ``` + +**Recommended config for existing projects** +The default configuration is quite strict specially with the usage of `any` and it's derivatives. For existing projects with a codebase that was developed with more lenient guidelines migrating to this configuration can be a bit overwhelming. + +You can customize your `eslint.config.js` file to disable some rules and make the transition easier. For example, you can create a `eslint.config.js` file with the following content: + +```javascript +const config = require('eslint-graph-config') + +module.exports = [ + ...config.default, + { + rules: { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + }, + }, + { + ignores: [ + 'library/*', // ignore its contents + '!node_modules/mylibrary/' // unignore `node_modules/mylibrary` directory + ] + } +] +``` + +## Tooling + +This package uses the following tools: +- [ESLint](https://eslint.org/) as the base linting tool +- [typescript-eslint](https://typescript-eslint.io/) for TypeScript support +- [ESLint Stylistic](https://eslint.style/) as the formatting tool + +**Why no prettier?** +Instead of prettier we use ESLint Stylistic which is a set of ESLint rules focused on formatting and styling code. As opposed to prettier, ESLint Stylistic runs entirely within ESLint and does not require a separate tool to be run (e.g. `prettier`, `eslint-plugin-prettier` and `eslint-config-prettier`). Additionally it's supposed to be [more efficient](https://eslint.style/guide/why#linters-vs-formatters) and [less opinionated](https://antfu.me/posts/why-not-prettier). + +## VSCode support + +If you are using VSCode you can install the [ESLint extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) to get real-time linting and formatting support. + +The following settings should be added to your `settings.json` file: +```json +{ + "editor.defaultFormatter": "dbaeumer.vscode-eslint", + "eslint.format.enable": true, + "eslint.experimental.useFlatConfig": true, + "eslint.workingDirectories": [{ "pattern": "./packages/*/" }] +} +``` + +Additionally you can configure the `Format document` keyboard shortcut to run `eslint --fix` on demand. \ No newline at end of file diff --git a/packages/eslint-graph-config/eslint.config.js b/packages/eslint-graph-config/eslint.config.js new file mode 100644 index 000000000..b4d8d3631 --- /dev/null +++ b/packages/eslint-graph-config/eslint.config.js @@ -0,0 +1,12 @@ +// This file only exists to enable linting on index.js +const config = require('./index') + +module.exports = [ + ...config.default, + { + rules: { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-var-requires': 'off', + }, + }, +] diff --git a/packages/eslint-graph-config/index.ts b/packages/eslint-graph-config/index.ts new file mode 100644 index 000000000..b9548595e --- /dev/null +++ b/packages/eslint-graph-config/index.ts @@ -0,0 +1,64 @@ +import eslint from '@eslint/js' +import globals from 'globals' +import noOnlyTests from 'eslint-plugin-no-only-tests' +import noSecrets from 'eslint-plugin-no-secrets' +import stylistic from '@stylistic/eslint-plugin' +import tseslint from 'typescript-eslint' + +export default [ + // Base eslint configuration + eslint.configs.recommended, + + // Enable linting with type information + // https://typescript-eslint.io/getting-started/typed-linting + ...tseslint.configs.recommendedTypeChecked, + + // Formatting and stylistic rules + stylistic.configs['recommended-flat'], + + // Custom config + { + languageOptions: { + parserOptions: { + project: ['../*/tsconfig.json', 'tsconfig.json'], + tsconfigRootDir: __dirname, + }, + globals: { + ...globals.node, + }, + }, + plugins: { + 'no-only-tests': noOnlyTests, + 'no-secrets': noSecrets, + }, + rules: { + 'prefer-const': 'warn', + '@typescript-eslint/no-inferrable-types': 'warn', + '@typescript-eslint/no-empty-function': 'warn', + 'no-only-tests/no-only-tests': 'error', + 'no-secrets/no-secrets': ['error', { tolerance: 4.1 }], + 'sort-imports': [ + 'warn', { + memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'], + ignoreCase: true, + allowSeparatedGroups: true, + }], + '@stylistic/brace-style': ['error', '1tbs'], + '@typescript-eslint/no-unused-vars': [ + 'error', + { + args: 'all', + argsIgnorePattern: '^_', + caughtErrors: 'all', + caughtErrorsIgnorePattern: '^_', + destructuredArrayIgnorePattern: '^_', + varsIgnorePattern: '^_', + ignoreRestSiblings: true, + }, + ], + }, + }, + { + ignores: ['**/dist/*', '**/node_modules/*', '**/build/*', '**/cache/*', '**/.graphclient/*'], + }, +] diff --git a/packages/eslint-graph-config/package.json b/packages/eslint-graph-config/package.json new file mode 100644 index 000000000..4ee7f5392 --- /dev/null +++ b/packages/eslint-graph-config/package.json @@ -0,0 +1,28 @@ +{ + "name": "eslint-graph-config", + "version": "0.0.1", + "description": "Linting and formatting rules for The Graph's TypeScript projects", + "main": "index.js", + "author": "The Graph Team", + "license": "GPL-2.0-or-later", + "scripts": { + "clean": "rm -rf index.js", + "lint": "eslint '**/*.{js,ts}' --ignore-pattern index.js --fix", + "build": "yarn clean && tsc" + }, + "dependencies": { + "@stylistic/eslint-plugin": "^1.6.2", + "eslint": "^8.56.0", + "eslint-plugin-no-only-tests": "^3.1.0", + "eslint-plugin-no-secrets": "^0.8.9", + "typescript-eslint": "^7.0.2" + }, + "devDependencies": { + "@types/eslint__js": "^8.42.3", + "@types/node": "^20.11.19", + "typescript": "^5.3.3" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } +} diff --git a/packages/eslint-graph-config/tsconfig.json b/packages/eslint-graph-config/tsconfig.json new file mode 100644 index 000000000..015450292 --- /dev/null +++ b/packages/eslint-graph-config/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "resolveJsonModule": true + }, + "include": ["index.ts", "typings/**/*.d.ts", "eslint.config.js"] +} diff --git a/packages/eslint-graph-config/typings/eslint-plugin-no-only-tests.d.ts b/packages/eslint-graph-config/typings/eslint-plugin-no-only-tests.d.ts new file mode 100644 index 000000000..1b3dbf7bd --- /dev/null +++ b/packages/eslint-graph-config/typings/eslint-plugin-no-only-tests.d.ts @@ -0,0 +1,5 @@ +declare module 'eslint-plugin-no-only-tests' { + import { FlatConfig } from 'typescript-eslint' + const plugin: FlatConfig.Plugin + export default plugin +} diff --git a/packages/eslint-graph-config/typings/eslint-plugin-no-secrets.d.ts b/packages/eslint-graph-config/typings/eslint-plugin-no-secrets.d.ts new file mode 100644 index 000000000..cde4120c2 --- /dev/null +++ b/packages/eslint-graph-config/typings/eslint-plugin-no-secrets.d.ts @@ -0,0 +1,5 @@ +declare module 'eslint-plugin-no-secrets' { + import { FlatConfig } from 'typescript-eslint' + const plugin: FlatConfig.Plugin + export default plugin +} diff --git a/packages/sdk/CHANGELOG.md b/packages/sdk/CHANGELOG.md new file mode 100644 index 000000000..20a787d51 --- /dev/null +++ b/packages/sdk/CHANGELOG.md @@ -0,0 +1,14 @@ +# @graphprotocol/sdk + +## 0.5.0 + +### Minor Changes + +- 554af2c: feat(utils): add utility to parse subgraph ids + +### Patch Changes + +- c5641c5: Ensure L2 aliased addresses are the correct length +- Updated dependencies +- Updated dependencies [554af2c] + - @graphprotocol/contracts@6.2.0 diff --git a/packages/sdk/package.json b/packages/sdk/package.json index ebc14d8ce..18497431e 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,16 +1,16 @@ { "name": "@graphprotocol/sdk", - "version": "0.3.0", + "version": "0.5.0", "description": "TypeScript based SDK to interact with The Graph protocol contracts", "main": "build/index.js", "types": "src/index.ts", "exports": { ".": { - "default": "./build/index.js", + "default": "./src/index.ts", "types": "./src/index.ts" }, "./gre": { - "default": "./build/gre/index.js", + "default": "./src/gre/index.ts", "types": "./src/gre/index.ts" } }, @@ -18,10 +18,10 @@ "author": "tomas@edgeandnode.com", "license": "MIT", "dependencies": { - "@arbitrum/sdk": "^3.1.12", + "@arbitrum/sdk": "~3.1.13", "@ethersproject/experimental": "^5.7.0", "@graphprotocol/common-ts": "^2.0.7", - "@graphprotocol/contracts": "workspace:^6.0.0", + "@graphprotocol/contracts": "workspace:^6.2.0", "@nomicfoundation/hardhat-network-helpers": "^1.0.9", "@nomiclabs/hardhat-ethers": "^2.2.3", "debug": "^4.3.4", diff --git a/packages/sdk/src/deployments/index.ts b/packages/sdk/src/deployments/index.ts index 2f90844ef..23b4b0e16 100644 --- a/packages/sdk/src/deployments/index.ts +++ b/packages/sdk/src/deployments/index.ts @@ -13,12 +13,17 @@ export { DeployType } from './lib/types/deploy' // Graph Network Contracts export { GraphNetworkAddressBook } from './network/deployment/address-book' export { loadGraphNetworkContracts } from './network/deployment/contracts/load' -export { deployGraphNetwork, deploy } from './network/deployment/contracts/deploy' +export { + deployGraphNetwork, + deployMockGraphNetwork, + deploy, +} from './network/deployment/contracts/deploy' export { isGraphNetworkContractName, GraphNetworkContractNameList, GraphNetworkL1ContractNameList, GraphNetworkL2ContractNameList, + GraphNetworkGovernedContractNameList, } from './network/deployment/contracts/list' export { GraphNetworkConfigGeneralParams, @@ -35,6 +40,7 @@ export * from './network/actions/governed' export * from './network/actions/bridge-config' export * from './network/actions/bridge-to-l1' export * from './network/actions/bridge-to-l2' +export * from './network/actions/pause' export type { GraphNetworkContracts } from './network/deployment/contracts/load' export type { GraphNetworkContractName } from './network/deployment/contracts/list' diff --git a/packages/sdk/src/deployments/lib/contracts/load.ts b/packages/sdk/src/deployments/lib/contracts/load.ts index a487a38bd..182d8b9c9 100644 --- a/packages/sdk/src/deployments/lib/contracts/load.ts +++ b/packages/sdk/src/deployments/lib/contracts/load.ts @@ -1,9 +1,9 @@ import { Contract, Signer, providers } from 'ethers' -import { getWrappedConnect, wrapCalls } from './tx-log' import { AddressBook } from '../address-book' import { loadArtifact } from '../deploy/artifacts' import type { ContractList } from '../types/contract' +import { getWrappedConnect, wrapCalls } from './wrap' /** * Loads a contract instance for a given contract name and address diff --git a/packages/sdk/src/deployments/lib/contracts/log.ts b/packages/sdk/src/deployments/lib/contracts/log.ts new file mode 100644 index 000000000..ebc19119b --- /dev/null +++ b/packages/sdk/src/deployments/lib/contracts/log.ts @@ -0,0 +1,62 @@ +import fs from 'fs' + +import type { ContractReceipt, ContractTransaction } from 'ethers' +import type { ContractParam } from '../types/contract' +import { logInfo } from '../../logger' + +export function logContractCall( + tx: ContractTransaction, + contractName: string, + fn: string, + args: Array, +) { + const msg: string[] = [] + msg.push(`> Sending transaction: ${contractName}.${fn}`) + msg.push(` = Sender: ${tx.from}`) + msg.push(` = Contract: ${tx.to}`) + msg.push(` = Params: [ ${args} ]`) + msg.push(` = TxHash: ${tx.hash}`) + + logToConsoleAndFile(msg) +} + +export function logContractDeploy( + tx: ContractTransaction, + contractName: string, + args: Array, +) { + const msg: string[] = [] + msg.push(`> Deploying contract: ${contractName}`) + msg.push(` = Sender: ${tx.from}`) + msg.push(` = Params: [ ${args} ]`) + msg.push(` = TxHash: ${tx.hash}`) + logToConsoleAndFile(msg) +} + +export function logContractDeployReceipt( + receipt: ContractReceipt, + creationCodeHash: string, + runtimeCodeHash: string, +) { + const msg: string[] = [] + msg.push(` = CreationCodeHash: ${creationCodeHash}`) + msg.push(` = RuntimeCodeHash: ${runtimeCodeHash}`) + logToConsoleAndFile(msg) + logContractReceipt(receipt) +} + +export function logContractReceipt(receipt: ContractReceipt) { + const msg: string[] = [] + msg.push(receipt.status ? ` ✔ Transaction succeeded!` : ` ✖ Transaction failed!`) + logToConsoleAndFile(msg) +} + +export function logToConsoleAndFile(msg: string[]) { + const isoDate = new Date().toISOString() + const fileName = `tx-${isoDate.substring(0, 10)}.log` + + msg.map((line) => { + logInfo(line) + fs.appendFileSync(fileName, `[${isoDate}] ${line}\n`) + }) +} diff --git a/packages/sdk/src/deployments/lib/contracts/tx-log.ts b/packages/sdk/src/deployments/lib/contracts/wrap.ts similarity index 52% rename from packages/sdk/src/deployments/lib/contracts/tx-log.ts rename to packages/sdk/src/deployments/lib/contracts/wrap.ts index c29480a04..411c5ceee 100644 --- a/packages/sdk/src/deployments/lib/contracts/tx-log.ts +++ b/packages/sdk/src/deployments/lib/contracts/wrap.ts @@ -1,15 +1,18 @@ -import fs from 'fs' import lodash from 'lodash' -import type { - Contract, - ContractFunction, - ContractReceipt, - ContractTransaction, - Signer, -} from 'ethers' +import type { Contract, ContractFunction, ContractTransaction, Signer } from 'ethers' import type { Provider } from '@ethersproject/providers' import type { ContractParam } from '../types/contract' +import { logContractCall, logContractReceipt } from './log' + +class WrappedContract { + // The meta-class properties + [key: string]: ContractFunction | any +} + +function isContractTransaction(call: ContractTransaction | any): call is ContractTransaction { + return typeof call === 'object' && (call as ContractTransaction).hash !== undefined +} /** * Modifies a contract connect function to return a contract wrapped with {@link wrapCalls} @@ -45,61 +48,32 @@ export function getWrappedConnect( * @returns the wrapped contract */ export function wrapCalls(contract: Contract, contractName: string): Contract { - const wrappedContract = lodash.cloneDeep(contract) + const wrappedContract = lodash.cloneDeep(contract) as WrappedContract for (const fn of Object.keys(contract.functions)) { - const call: ContractFunction = contract.functions[fn] - const override = async (...args: Array): Promise => { - // Make the call - const tx = await call(...args) - logContractCall(tx, contractName, fn, args) + const call = contract.functions[fn] + const override = async (...args: Array): Promise => { + const response = await call(...args) + + // If it's a read only call, return the response + if (!isContractTransaction(response)) { + return Array.isArray(response) && response.length === 1 ? response[0] : response + } - // Wait for confirmation - const receipt = await contract.provider.waitForTransaction(tx.hash) - logContractReceipt(tx, receipt) - return tx + // Otherwise it's a tx, log the details + logContractCall(response, contractName, fn, args) + + // And wait for confirmation + const receipt = await contract.provider.waitForTransaction(response.hash) + logContractReceipt(receipt) + + // Finally return the tx response + return response } - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore wrappedContract[fn] = override wrappedContract.functions[fn] = override } - return wrappedContract -} - -function logContractCall( - tx: ContractTransaction, - contractName: string, - fn: string, - args: Array, -) { - const msg: string[] = [] - msg.push(`> Sent transaction ${contractName}.${fn}`) - msg.push(` sender: ${tx.from}`) - msg.push(` contract: ${tx.to}`) - msg.push(` params: [ ${args} ]`) - msg.push(` txHash: ${tx.hash}`) - - logToConsoleAndFile(msg) -} - -function logContractReceipt(tx: ContractTransaction, receipt: ContractReceipt) { - const msg: string[] = [] - msg.push( - receipt.status ? `✔ Transaction succeeded: ${tx.hash}` : `✖ Transaction failed: ${tx.hash}`, - ) - - logToConsoleAndFile(msg) -} - -function logToConsoleAndFile(msg: string[]) { - const isoDate = new Date().toISOString() - const fileName = `tx-${isoDate.substring(0, 10)}.log` - - msg.map((line) => { - console.log(line) - fs.appendFileSync(fileName, `[${isoDate}] ${line}\n`) - }) + return wrappedContract as Contract } diff --git a/packages/sdk/src/deployments/lib/deploy/contract.ts b/packages/sdk/src/deployments/lib/deploy/contract.ts index e3a09219c..ea8681493 100644 --- a/packages/sdk/src/deployments/lib/deploy/contract.ts +++ b/packages/sdk/src/deployments/lib/deploy/contract.ts @@ -10,6 +10,7 @@ import type { DeployFunction, DeployAddressBookFunction, } from '../types/deploy' +import { logContractDeploy, logContractDeployReceipt } from '../contracts/log' /** * Deploys a contract @@ -59,15 +60,13 @@ export const deployContract: DeployFunction = async ( const factory = getContractFactory(name, libraries) const contract = await factory.connect(sender).deploy(...args) const txHash = contract.deployTransaction.hash - logInfo(`> Deploy ${name}, txHash: ${txHash}`) - await sender.provider.waitForTransaction(txHash) + logContractDeploy(contract.deployTransaction, name, args) + const receipt = await sender.provider.waitForTransaction(txHash) // Receipt const creationCodeHash = hashHexString(factory.bytecode) const runtimeCodeHash = hashHexString(await sender.provider.getCode(contract.address)) - logInfo(`= CreationCodeHash: ${creationCodeHash}`) - logInfo(`= RuntimeCodeHash: ${runtimeCodeHash}`) - logInfo(`${name} has been deployed to address: ${contract.address}`) + logContractDeployReceipt(receipt, creationCodeHash, runtimeCodeHash) return { contract, creationCodeHash, runtimeCodeHash, txHash, libraries } } diff --git a/packages/sdk/src/deployments/network/actions/pause.ts b/packages/sdk/src/deployments/network/actions/pause.ts new file mode 100644 index 000000000..d2be153ab --- /dev/null +++ b/packages/sdk/src/deployments/network/actions/pause.ts @@ -0,0 +1,29 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { GraphNetworkContracts } from '../deployment/contracts/load' +import { GraphNetworkAction } from './types' + +export const setPausedProtocol: GraphNetworkAction<{ paused: boolean }> = async ( + contracts: GraphNetworkContracts, + governorOrPauseGuardian: SignerWithAddress, + args: { paused: boolean }, +): Promise => { + const { paused } = args + const { Controller } = contracts + + console.log(`\nSetting protocol paused to ${paused}...`) + const tx = await Controller.connect(governorOrPauseGuardian).setPaused(paused) + await tx.wait() +} + +export const setPausedBridge: GraphNetworkAction<{ paused: boolean }> = async ( + contracts: GraphNetworkContracts, + governorOrPauseGuardian: SignerWithAddress, + args: { paused: boolean }, +): Promise => { + const { paused } = args + const { GraphTokenGateway } = contracts + + console.log(`\nSetting bridge ${GraphTokenGateway.address} paused to ${paused}...`) + const tx = await GraphTokenGateway.connect(governorOrPauseGuardian).setPaused(paused) + await tx.wait() +} diff --git a/packages/sdk/src/deployments/network/actions/staking.ts b/packages/sdk/src/deployments/network/actions/staking.ts index 7e7a16084..e7cfa5c69 100644 --- a/packages/sdk/src/deployments/network/actions/staking.ts +++ b/packages/sdk/src/deployments/network/actions/staking.ts @@ -48,6 +48,10 @@ export const allocateFrom: GraphNetworkAction<{ const metadata = ethers.constants.HashZero console.log(`\nAllocating ${amount} tokens on ${allocationId}...`) + let extraArgs: ethers.Overrides = {} + if (process.env.CI) { + extraArgs.gasLimit = BigNumber.from('400000') + } const tx = await contracts.Staking.connect(indexer).allocateFrom( indexer.address, subgraphDeploymentID, @@ -55,6 +59,7 @@ export const allocateFrom: GraphNetworkAction<{ allocationId, metadata, proof, + extraArgs ) await tx.wait() } diff --git a/packages/sdk/src/deployments/network/deployment/contracts/deploy.ts b/packages/sdk/src/deployments/network/deployment/contracts/deploy.ts index 951e36b5c..219587f66 100644 --- a/packages/sdk/src/deployments/network/deployment/contracts/deploy.ts +++ b/packages/sdk/src/deployments/network/deployment/contracts/deploy.ts @@ -13,17 +13,23 @@ import { type GraphNetworkContractName, GraphNetworkL1ContractNameList, GraphNetworkL2ContractNameList, + GraphNetworkGovernedContractNameList, } from './list' import { getContractConfig, loadCallParams, readConfig } from '../../../lib/config' import { logDebug } from '../../../logger' -import type { Signer, providers } from 'ethers' +import type { ContractTransaction, Signer, providers } from 'ethers' import type { DeployData, DeployResult } from '../../../lib/types/deploy' import type { AddressBook } from '../../../lib/address-book' import { GraphNetworkAddressBook } from '../address-book' import { isContractDeployed } from '../../../lib/deploy/deploy' import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' -import { Contract, ethers } from 'ethers' +import { Contract, Wallet, ethers } from 'ethers' +import { acceptOwnership } from '../../actions/governed' +import { setPausedProtocol } from '../../actions/pause' +import { GraphNetworkContracts, loadGraphNetworkContracts } from './load' +import { setCode } from '../../../../helpers/code' +import { logContractCall, logContractReceipt } from '../../../lib/contracts/log' export async function deployGraphNetwork( addressBookPath: string, @@ -32,16 +38,21 @@ export async function deployGraphNetwork( deployer: SignerWithAddress, provider: providers.Provider, opts?: { + governor?: SignerWithAddress skipConfirmation?: boolean forceDeploy?: boolean buildAcceptTx?: boolean l2Deploy?: boolean + enableTxLogging?: boolean }, -) { +): Promise { // Opts + const governor = opts?.governor ?? undefined const skipConfirmation = opts?.skipConfirmation ?? false const forceDeploy = opts?.forceDeploy ?? false const buildAcceptTx = opts?.buildAcceptTx ?? false + const l2Deploy = opts?.l2Deploy ?? false + const enableTxLogging = opts?.enableTxLogging ?? true // Snapshot deployer const beforeDeployerNonce = await deployer.getTransactionCount() @@ -56,10 +67,10 @@ export async function deployGraphNetwork( const contractList: GraphNetworkContractName[] = [ ...GraphNetworkSharedContractNameList.filter((c) => c !== 'AllocationExchange'), ] - if (!opts?.l2Deploy && isGraphL1ChainId(chainId)) { + if (!l2Deploy && isGraphL1ChainId(chainId)) { contractList.push(...GraphNetworkL1ContractNameList) } - if (opts?.l2Deploy || isGraphL2ChainId(chainId)) { + if (l2Deploy || isGraphL2ChainId(chainId)) { contractList.push(...GraphNetworkL2ContractNameList) } contractList.push('AllocationExchange') @@ -143,7 +154,12 @@ export async function deployGraphNetwork( const params = loadCallParams(call.params, addressBook, deployer.address) logDebug(`- Params: ${params.join(', ')}`) const overrides = process.env.CI ? { gasLimit: 2_000_000 } : {} - await entry.contract.contract.connect(deployer).functions[call.fn](...params, overrides) + const response: ContractTransaction = await entry.contract.contract + .connect(deployer) + .functions[call.fn](...params, overrides) + logContractCall(response, entry.name, call.fn, params) + const receipt = await entry.contract.contract.provider.waitForTransaction(response.hash) + logContractReceipt(receipt) } catch (error) { // TODO: can we clean this up? // Fallback for StakingExtension methods @@ -170,6 +186,31 @@ export async function deployGraphNetwork( } else { logDebug('Nothing to do') } + + //////////////////////////////////////// + // Load contracts + //////////////////////////////////////// + const loadedContracts = loadGraphNetworkContracts(addressBookPath, chainId, provider, undefined, { + l2Load: l2Deploy, + enableTxLogging: enableTxLogging, + }) + + //////////////////////////////////////// + // Post deploy + //////////////////////////////////////// + // If a governor was provided, accept ownership of contracts and unpause the protocol + if (governor) { + const txs: ContractTransaction[] = [] + for (const contract of GraphNetworkGovernedContractNameList) { + const tx = await acceptOwnership(loadedContracts, governor, { contractName: contract }) + if (tx) { + txs.push() + } + } + await Promise.all(txs.map((tx) => tx.wait())) + await setPausedProtocol(loadedContracts, governor, { paused: false }) + } + //////////////////////////////////////// // Print summary //////////////////////////////////////// @@ -187,6 +228,26 @@ export async function deployGraphNetwork( ethers.constants.EtherSymbol } ${spent}`, ) + + return loadedContracts +} + +export async function deployMockGraphNetwork(l2Deploy: boolean) { + // Contract list + const contractList: GraphNetworkContractName[] = [ + ...GraphNetworkSharedContractNameList.filter((c) => c !== 'AllocationExchange'), + ] + contractList.push(...(l2Deploy ? GraphNetworkL2ContractNameList : GraphNetworkL1ContractNameList)) + contractList.push('AllocationExchange') + + const contracts: any = {} + for (const name of contractList) { + const fake = Wallet.createRandom() + await setCode(fake.address, '0x1234') + contracts[name] = new Contract(fake.address, [], fake) + } + + return contracts as GraphNetworkContracts // :eyes: } export const deploy = async ( diff --git a/packages/sdk/src/deployments/network/deployment/contracts/list.ts b/packages/sdk/src/deployments/network/deployment/contracts/list.ts index 11fdccb6f..14449a5ac 100644 --- a/packages/sdk/src/deployments/network/deployment/contracts/list.ts +++ b/packages/sdk/src/deployments/network/deployment/contracts/list.ts @@ -52,3 +52,10 @@ export function isGraphNetworkContractName(name: unknown): name is GraphNetworkC GraphNetworkContractNameList.includes(name as GraphNetworkContractName) ) } + +export const GraphNetworkGovernedContractNameList: GraphNetworkContractName[] = [ + 'GraphToken', + 'Controller', + 'GraphProxyAdmin', + 'SubgraphNFT', +] diff --git a/packages/sdk/src/deployments/network/deployment/contracts/load.ts b/packages/sdk/src/deployments/network/deployment/contracts/load.ts index 6f4ca788d..74ab9e1a8 100644 --- a/packages/sdk/src/deployments/network/deployment/contracts/load.ts +++ b/packages/sdk/src/deployments/network/deployment/contracts/load.ts @@ -105,7 +105,7 @@ export function loadGraphNetworkContracts( opts?: { enableTxLogging?: boolean strictAssert?: boolean - l2Load: boolean + l2Load?: boolean }, ): GraphNetworkContracts { artifactsPath = artifactsPath ?? getArtifactsPath() @@ -117,7 +117,7 @@ export function loadGraphNetworkContracts( addressBook, artifactsPath, signerOrProvider, - opts?.enableTxLogging ?? false, + opts?.enableTxLogging ?? true, GraphNetworkOptionalContractNameList as unknown as GraphNetworkContractName[], // This is ugly but safe ) @@ -144,7 +144,7 @@ export function loadGraphNetworkContracts( addressBook, artifactsPath, signerOrProvider, - opts?.enableTxLogging ?? false, + opts?.enableTxLogging ?? true, new Contract( staking.address, mergeABIs( diff --git a/packages/sdk/src/gre/README.md b/packages/sdk/src/gre/README.md index f5e49e3a7..1605d0a55 100644 --- a/packages/sdk/src/gre/README.md +++ b/packages/sdk/src/gre/README.md @@ -7,6 +7,7 @@ GRE is a hardhat plugin that extends hardhat's runtime environment to inject add - Provides a simple interface to interact with protocol contracts - Exposes protocol configuration via graph config file and address book - Provides account management methods for convenience +- Detailed logging of transactions to file - Multichain! Supports both L1 and L2 layers of the protocol simultaneously - Integrates seamlessly with [hardhat-secure-accounts](https://www.npmjs.com/package/hardhat-secure-accounts) - Convenience method to create tasks that use GRE @@ -129,16 +130,16 @@ The priority for the address book is: GRE accepts a few parameters when being initialized. When using GRE in the context of a hardhat task these parameters would typically be configured as task options. -In order to simplify the creation of hardhat tasks that will make use of GRE and would require several options to be defined we provide a convenience method: `graphTask`. This is a drop in replacement for hardhat's `task` that includes GRE related boilerplate, you can still customize the task as you would do with `task`. +In order to simplify the creation of hardhat tasks that will make use of GRE and would require several options to be defined we provide a convenience method: `greTask`. This is a drop in replacement for hardhat's `task` that includes GRE related boilerplate, you can still customize the task as you would do with `task`. you avoid having to define GRE's options on all of your tasks. Here is an example of a task using this convenience method: ```ts -import { graphTask } from '../../gre/gre' +import { greTask } from '../../gre/gre' -graphTask('hello-world', 'Say hi!', async (args, hre) => { +greTask('hello-world', 'Say hi!', async (args, hre) => { console.log('hello world') const graph = hre.graph(args) }) @@ -154,6 +155,7 @@ OPTIONS: --address-book Path to the address book file. --disable-secure-accounts Disable secure accounts. + --enable-tx-logging Enable transaction logging. --graph-config Path to the graph config file for the network specified using --network. --l1-graph-config Path to the graph config file for the L1 network. --l2-graph-config Path to the graph config file for the L2 network. @@ -163,6 +165,27 @@ hello-world: Say hi! For global options help run: hardhat help ``` +### Transaction Logging + +By default all transactions executed via GRE will be logged to a file. The file will be created on the first transaction with the following convention `tx-.log`. Here is a sample log file: + +``` +[2024-01-15T14:33:26.747Z] > Sending transaction: GraphToken.addMinter +[2024-01-15T14:33:26.747Z] = Sender: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1 +[2024-01-15T14:33:26.747Z] = Contract: 0x428aAe4Fa354c21600b6ec0077F2a6855C7dcbC8 +[2024-01-15T14:33:26.747Z] = Params: [ 0x05eA50dc2C0389117A067D393e0395ACc32c53b6 ] +[2024-01-15T14:33:26.747Z] = TxHash: 0xa9096e5f9f9a2208202ac3a8b895561dc3f781fa7e19350b0855098a08d193f7 +[2024-01-15T14:33:26.750Z] ✔ Transaction succeeded! +[2024-01-15T14:33:26.777Z] > Sending transaction: GraphToken.renounceMinter +[2024-01-15T14:33:26.777Z] = Sender: 0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1 +[2024-01-15T14:33:26.777Z] = Contract: 0x428aAe4Fa354c21600b6ec0077F2a6855C7dcbC8 +[2024-01-15T14:33:26.777Z] = Params: [ ] +[2024-01-15T14:33:26.777Z] = TxHash: 0x48233b256a1f98cb3fecc3dd48d7f7c0175042142e1ca7b9b1f9fc91169bb588 +[2024-01-15T14:33:26.780Z] ✔ Transaction succeeded! +``` + +If you want to disable transaction logging you can do so by setting the `enableTxLogging` option to `false` when initializing GRE: ```g=graph({ disableSecureAccounts: true })``` + ## API GRE exposes functionality via a simple API: diff --git a/packages/sdk/src/gre/accounts.ts b/packages/sdk/src/gre/accounts.ts index eb8aae5ce..1d1de08cd 100644 --- a/packages/sdk/src/gre/accounts.ts +++ b/packages/sdk/src/gre/accounts.ts @@ -21,18 +21,11 @@ const namedAccountList: AccountNames[] = [ export async function getNamedAccounts( provider: EthersProviderWrapper, graphConfigPath: string, - impersonate?: boolean, ): Promise { const namedAccounts = namedAccountList.reduce( async (accountsPromise, name) => { const accounts = await accountsPromise const address = getItemValue(readConfig(graphConfigPath, true), `general/${name}`) - - // If we are impersonating, we need to set the balance of the account - if (impersonate) { - await provider.send('hardhat_impersonateAccount', [address]) - await provider.send('hardhat_setBalance', [address, '0x56BC75E2D63100000']) // 100 ETH - } accounts[name] = await SignerWithAddress.create(provider.getSigner(address)) return accounts }, @@ -70,6 +63,15 @@ export async function getTestAccounts( }) } +export async function getAllAccounts( + provider: EthersProviderWrapper, +): Promise { + const accounts = await provider.listAccounts() + return await Promise.all( + accounts.map(async (account) => await SignerWithAddress.create(provider.getSigner(account))), + ) +} + export async function getWallets( networks: NetworksConfig, chainId: number, diff --git a/packages/sdk/src/gre/config.ts b/packages/sdk/src/gre/config.ts index 570391bfa..f8e718bd9 100644 --- a/packages/sdk/src/gre/config.ts +++ b/packages/sdk/src/gre/config.ts @@ -36,10 +36,12 @@ export function getAddressBookPath( ): string { logDebug('== Getting address book path') logDebug(`Graph base dir: ${hre.config.paths.graph}`) - logDebug(`1) opts.addressBookPath: ${opts.addressBook}`) - logDebug(`2) hre.config.graph.addressBook: ${hre.config.graph?.addressBook}`) + logDebug(`1) opts.addressBook: ${opts.addressBook}`) + logDebug(`2) hre.network.config.addressBook: ${hre.network.config?.addressBook}`) + logDebug(`3) hre.config.graph.addressBook: ${hre.config.graph?.addressBook}`) - let addressBookPath = opts.addressBook ?? hre.config.graph?.addressBook + let addressBookPath = + opts.addressBook ?? hre.network.config?.addressBook ?? hre.config.graph?.addressBook if (addressBookPath === undefined) { throw new GREPluginError('Must set a an addressBook path!') diff --git a/packages/sdk/src/gre/gre.ts b/packages/sdk/src/gre/gre.ts index 76470e8ed..642b3d20b 100644 --- a/packages/sdk/src/gre/gre.ts +++ b/packages/sdk/src/gre/gre.ts @@ -5,7 +5,14 @@ import { HardhatConfig, HardhatRuntimeEnvironment, HardhatUserConfig } from 'har import { EthersProviderWrapper } from '@nomiclabs/hardhat-ethers/internal/ethers-provider-wrapper' import { GraphNetworkAddressBook, readConfig, loadGraphNetworkContracts } from '..' -import { getDeployer, getNamedAccounts, getTestAccounts, getWallet, getWallets } from './accounts' +import { + getAllAccounts, + getDeployer, + getNamedAccounts, + getTestAccounts, + getWallet, + getWallets, +} from './accounts' import { getAddressBookPath, getChains, getDefaultProviders, getGraphConfigPaths } from './config' import { getSecureAccountsProvider } from './providers' import { logDebug, logWarn } from './helpers/logger' @@ -44,7 +51,7 @@ export const greExtendEnvironment = (hre: HardhatRuntimeEnvironment) => { logDebug('== Features') // Tx logging - const enableTxLogging = opts.enableTxLogging ?? false + const enableTxLogging = opts.enableTxLogging ?? true logDebug(`Tx logging: ${enableTxLogging ? 'enabled' : 'disabled'}`) // Secure accounts @@ -198,7 +205,11 @@ function buildGraphNetworkEnvironment( config.defaults = getDefaults(config, isHHL1) return config }), - contracts: lazyObject(() => loadGraphNetworkContracts(addressBookPath, chainId, provider)), + contracts: lazyObject(() => + loadGraphNetworkContracts(addressBookPath, chainId, provider, undefined, { + enableTxLogging, + }), + ), getWallets: lazyFunction(() => () => getWallets()), getWallet: lazyFunction(() => (address: string) => getWallet(address)), getDeployer: lazyFunction( @@ -209,12 +220,14 @@ function buildGraphNetworkEnvironment( getNamedAccounts( fork ? provider : await getUpdatedProvider('getNamedAccounts'), graphConfigPath, - fork, ), ), getTestAccounts: lazyFunction( () => async () => getTestAccounts(await getUpdatedProvider('getTestAccounts'), graphConfigPath), ), + getAllAccounts: lazyFunction( + () => async () => getAllAccounts(await getUpdatedProvider('getAllAccounts')), + ), } } diff --git a/packages/sdk/src/gre/helpers/argv.ts b/packages/sdk/src/gre/helpers/argv.ts index a6b2eb243..2708d35b5 100644 --- a/packages/sdk/src/gre/helpers/argv.ts +++ b/packages/sdk/src/gre/helpers/argv.ts @@ -11,7 +11,7 @@ export function getGREOptsFromArgv(): GraphRuntimeEnvironmentOptions { graphConfig: getArgv(1), l1GraphConfig: getArgv(2), l2GraphConfig: getArgv(3), - disableSecureAccounts: getArgv(4), - fork: getArgv(5), + disableSecureAccounts: getArgv(4) === 'true', + fork: getArgv(5) === 'true', } } diff --git a/packages/sdk/src/gre/index.ts b/packages/sdk/src/gre/index.ts index 730c23a13..28e2741b6 100644 --- a/packages/sdk/src/gre/index.ts +++ b/packages/sdk/src/gre/index.ts @@ -14,6 +14,5 @@ extendEnvironment(greExtendEnvironment) // Exports export * from './types' -export { graphTask } from './tasks/task' -export { GRE_TASK_PARAMS } from './tasks/defaults' +export { greTask as greTask } from './task' export { getGREOptsFromArgv } from './helpers/argv' diff --git a/packages/sdk/src/gre/task.ts b/packages/sdk/src/gre/task.ts new file mode 100644 index 000000000..ac67ec507 --- /dev/null +++ b/packages/sdk/src/gre/task.ts @@ -0,0 +1,32 @@ +import { task } from 'hardhat/config' +import { ActionType, ConfigurableTaskDefinition } from 'hardhat/types/runtime' + +function grePrefix(text: string): string { + return `[GRE] ${text}` +} + +export function greTask( + name: string, + description?: string | undefined, + action?: ActionType | undefined, +): ConfigurableTaskDefinition { + return task(name, description, action) + .addOptionalParam('addressBook', grePrefix('Path to the address book file.')) + .addOptionalParam( + 'graphConfig', + grePrefix( + 'Path to the graph config file for the network specified using --network. Lower priority than --l1GraphConfig and --l2GraphConfig.', + ), + ) + .addOptionalParam( + 'l1GraphConfig', + grePrefix('Path to the graph config file for the L1 network.'), + ) + .addOptionalParam( + 'l2GraphConfig', + grePrefix('Path to the graph config file for the L2 network.'), + ) + .addFlag('disableSecureAccounts', grePrefix('Disable secure accounts plugin.')) + .addFlag('enableTxLogging', grePrefix('Enable transaction logging.')) + .addFlag('fork', grePrefix('Wether or not the network is a fork.')) +} diff --git a/packages/sdk/src/gre/tasks/defaults.ts b/packages/sdk/src/gre/tasks/defaults.ts deleted file mode 100644 index e14b37fe0..000000000 --- a/packages/sdk/src/gre/tasks/defaults.ts +++ /dev/null @@ -1,37 +0,0 @@ -export const GRE_TASK_PARAMS = { - addressBook: { - description: 'The path to your address book file', - default: './addresses.json', - }, - graphConfig: { - description: 'The path to the config file', - default: './config/graph.mainnet.yml', - }, - providerUrl: { - description: 'The URL of an Ethereum provider', - default: 'http://127.0.0.1:8545', - }, - mnemonic: { - description: 'The mnemonic for an account which will pay for gas', - default: 'myth like bonus scare over problem client lizard pioneer submit female collect', - }, - accountNumber: { - description: 'The account number of the mnemonic', - default: '0', - }, - force: { - description: "Deploy contract even if it's already deployed", - }, - skipConfirmation: { - description: 'Skip confirmation prompt on write actions', - default: false, - }, - arbitrumAddressBook: { - description: 'The path to the address book file for Arbitrum deployments', - default: './arbitrum-addresses.json', - }, - l2ProviderUrl: { - description: 'The URL of an Arbitrum provider (only for bridge commands)', - default: 'https://rinkeby.arbitrum.io/rpc', - }, -} diff --git a/packages/sdk/src/gre/tasks/task.ts b/packages/sdk/src/gre/tasks/task.ts deleted file mode 100644 index f0269eff4..000000000 --- a/packages/sdk/src/gre/tasks/task.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { task } from 'hardhat/config' -import { ActionType, ConfigurableTaskDefinition } from 'hardhat/types/runtime' - -export function graphTask( - name: string, - description?: string, - action?: ActionType, -): ConfigurableTaskDefinition { - return task(name, description, action) - .addOptionalParam('addressBook', 'Path to the address book file.') - .addOptionalParam( - 'graphConfig', - 'Path to the graph config file for the network specified using --network.', - ) - .addOptionalParam('l1GraphConfig', 'Path to the graph config file for the L1 network.') - .addOptionalParam('l2GraphConfig', 'Path to the graph config file for the L2 network.') - .addFlag('disableSecureAccounts', 'Disable secure accounts.') -} diff --git a/packages/sdk/src/gre/type-extensions.ts b/packages/sdk/src/gre/type-extensions.ts index f137e102b..a653a09fc 100644 --- a/packages/sdk/src/gre/type-extensions.ts +++ b/packages/sdk/src/gre/type-extensions.ts @@ -21,18 +21,22 @@ declare module 'hardhat/types/config' { export interface HardhatNetworkConfig { graphConfig?: string + addressBook?: string } export interface HardhatNetworkUserConfig { graphConfig?: string + addressBook?: string } export interface HttpNetworkConfig { graphConfig?: string + addressBook?: string } export interface HttpNetworkUserConfig { graphConfig?: string + addressBook?: string } export interface ProjectPathsConfig { diff --git a/packages/sdk/src/gre/types.ts b/packages/sdk/src/gre/types.ts index 66ee237f7..fc10304df 100644 --- a/packages/sdk/src/gre/types.ts +++ b/packages/sdk/src/gre/types.ts @@ -40,6 +40,7 @@ export interface GraphNetworkEnvironment { addressBook: GraphNetworkAddressBook getNamedAccounts: () => Promise getTestAccounts: () => Promise + getAllAccounts: () => Promise getDeployer: () => Promise getWallets: () => Promise getWallet: (address: string) => Promise diff --git a/packages/sdk/src/helpers/arbitrum.ts b/packages/sdk/src/helpers/arbitrum.ts index b2da9c50e..ae91d662b 100644 --- a/packages/sdk/src/helpers/arbitrum.ts +++ b/packages/sdk/src/helpers/arbitrum.ts @@ -2,8 +2,112 @@ import fs from 'fs' import { addCustomNetwork } from '@arbitrum/sdk' import { applyL1ToL2Alias } from '../utils/arbitrum/' import { impersonateAccount } from './impersonate' +import { Wallet, ethers, providers } from 'ethers' import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' +import { DeployType, deploy } from '../deployments' +import type { BridgeMock, InboxMock, OutboxMock } from '@graphprotocol/contracts' +import { setCode } from './code' + +export interface L1ArbitrumMocks { + bridgeMock: BridgeMock + inboxMock: InboxMock + outboxMock: OutboxMock + routerMock: Wallet +} + +export interface L2ArbitrumMocks { + routerMock: Wallet +} + +export async function deployL1MockBridge( + deployer: SignerWithAddress, + arbitrumAddressBook: string, + provider: providers.Provider, +): Promise { + // Deploy mock contracts + const bridgeMock = (await deploy(DeployType.Deploy, deployer, { name: 'BridgeMock' })) + .contract as BridgeMock + const inboxMock = (await deploy(DeployType.Deploy, deployer, { name: 'InboxMock' })) + .contract as InboxMock + const outboxMock = (await deploy(DeployType.Deploy, deployer, { name: 'OutboxMock' })) + .contract as OutboxMock + + // "deploy" router - set dummy code so that it appears as a contract + const routerMock = Wallet.createRandom() + await setCode(routerMock.address, '0x1234') + + // Configure mock contracts + await bridgeMock.connect(deployer).setInbox(inboxMock.address, true) + await bridgeMock.connect(deployer).setOutbox(outboxMock.address, true) + await inboxMock.connect(deployer).setBridge(bridgeMock.address) + await outboxMock.connect(deployer).setBridge(bridgeMock.address) + + // Update address book + const deployment = fs.existsSync(arbitrumAddressBook) + ? JSON.parse(fs.readFileSync(arbitrumAddressBook, 'utf-8')) + : {} + const addressBook = { + '1337': { + L1GatewayRouter: { + address: routerMock.address, + }, + IInbox: { + address: inboxMock.address, + }, + }, + '412346': { + L2GatewayRouter: { + address: deployment['412346']?.L2GatewayRouter?.address ?? '', + }, + }, + } + + fs.writeFileSync(arbitrumAddressBook, JSON.stringify(addressBook)) + + return { + bridgeMock: bridgeMock.connect(provider), + inboxMock: inboxMock.connect(provider), + outboxMock: outboxMock.connect(provider), + routerMock: routerMock.connect(provider), + } +} + +export async function deployL2MockBridge( + deployer: SignerWithAddress, + arbitrumAddressBook: string, + provider: providers.Provider, +): Promise { + // "deploy" router - set dummy code so that it appears as a contract + const routerMock = Wallet.createRandom() + await setCode(routerMock.address, '0x1234') + + // Update address book + const deployment = fs.existsSync(arbitrumAddressBook) + ? JSON.parse(fs.readFileSync(arbitrumAddressBook, 'utf-8')) + : {} + const addressBook = { + '1337': { + L1GatewayRouter: { + address: deployment['1337']?.L1GatewayRouter?.address, + }, + IInbox: { + address: deployment['1337']?.IInbox?.address, + }, + }, + '412346': { + L2GatewayRouter: { + address: routerMock.address, + }, + }, + } + + fs.writeFileSync(arbitrumAddressBook, JSON.stringify(addressBook)) + + return { + routerMock: routerMock.connect(provider), + } +} export async function getL2SignerFromL1(l1Address: string): Promise { const l2Address = applyL1ToL2Alias(l1Address) @@ -20,3 +124,20 @@ export function addLocalNetwork(deploymentFile: string) { customL2Network: deployment.l2Network, }) } + +// Use prefunded genesis address to fund accounts +// See: https://docs.arbitrum.io/node-running/how-tos/local-dev-node#default-endpoints-and-addresses +export async function fundLocalAccounts( + accounts: SignerWithAddress[], + provider: providers.Provider, +) { + for (const account of accounts) { + const amount = ethers.utils.parseEther('10') + const wallet = new Wallet('b6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659') + const tx = await wallet.connect(provider).sendTransaction({ + value: amount, + to: account.address, + }) + await tx.wait() + } +} diff --git a/packages/sdk/src/helpers/impersonate.ts b/packages/sdk/src/helpers/impersonate.ts index b4c3212ed..8f7858322 100644 --- a/packages/sdk/src/helpers/impersonate.ts +++ b/packages/sdk/src/helpers/impersonate.ts @@ -4,5 +4,8 @@ import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' export async function impersonateAccount(address: string): Promise { const hre = await import('hardhat') await hardhatImpersonateAccount(address) - return hre.ethers.getSigner(address) + + // This allows the dynamic import to work on both ts and js + const ethers = hre.ethers ?? hre.default.ethers + return ethers.getSigner(address) } diff --git a/packages/sdk/src/helpers/mine.ts b/packages/sdk/src/helpers/mine.ts index ff3558b3e..a6175c85d 100644 --- a/packages/sdk/src/helpers/mine.ts +++ b/packages/sdk/src/helpers/mine.ts @@ -18,10 +18,16 @@ export async function mineUpTo(blockNumber: string | number | BigNumber): Promis export async function setAutoMine(autoMine: boolean): Promise { const hre = await import('hardhat') - return hre.network.provider.send('evm_setAutomine', [autoMine]) + + // This allows the dynamic import to work on both ts and js + const network = hre.network ?? hre.default.network + return network.provider.send('evm_setAutomine', [autoMine]) } export async function setIntervalMining(interval: number): Promise { const hre = await import('hardhat') - return hre.network.provider.send('evm_setIntervalMining', [interval]) + + // This allows the dynamic import to work on both ts and js + const network = hre.network ?? hre.default.network + return network.provider.send('evm_setIntervalMining', [interval]) } diff --git a/packages/sdk/src/utils/arbitrum/address.ts b/packages/sdk/src/utils/arbitrum/address.ts index c9168eff8..6f92890b7 100644 --- a/packages/sdk/src/utils/arbitrum/address.ts +++ b/packages/sdk/src/utils/arbitrum/address.ts @@ -1,3 +1,4 @@ +import { hexZeroPad } from 'ethers/lib/utils' import { toBN } from '../units' // Adapted from: @@ -8,5 +9,5 @@ export const applyL1ToL2Alias = (l1Address: string): string => { const l2AddressAsNumber = l1AddressAsNumber.add(offset) const mask = toBN(2).pow(160) - return l2AddressAsNumber.mod(mask).toHexString() + return hexZeroPad(l2AddressAsNumber.mod(mask).toHexString(), 20) } diff --git a/packages/sdk/src/utils/bytes.ts b/packages/sdk/src/utils/bytes.ts index eeecb6063..551be450c 100644 --- a/packages/sdk/src/utils/bytes.ts +++ b/packages/sdk/src/utils/bytes.ts @@ -1,3 +1,8 @@ +import { ethers } from 'ethers' import { hexlify, randomBytes } from 'ethers/lib/utils' export const randomHexBytes = (n = 32): string => hexlify(randomBytes(n)) + +export const base58ToHex = (base58: string): string => { + return ethers.utils.hexlify(ethers.utils.base58.decode(base58)) +} diff --git a/packages/sdk/src/utils/subgraph.ts b/packages/sdk/src/utils/subgraph.ts index af5a28ef3..b696f60b8 100644 --- a/packages/sdk/src/utils/subgraph.ts +++ b/packages/sdk/src/utils/subgraph.ts @@ -1,6 +1,6 @@ import { BigNumber, ethers } from 'ethers' import { solidityKeccak256 } from 'ethers/lib/utils' -import { randomHexBytes } from './bytes' +import { base58ToHex, randomHexBytes } from './bytes' export interface PublishSubgraph { subgraphDeploymentID: string @@ -36,3 +36,8 @@ export const buildSubgraph = (): PublishSubgraph => { subgraphMetadata: randomHexBytes(), } } + +export const subgraphIdToHex = (id: string): string => { + id = id.startsWith('Qm') ? id : `Qm${id}` + return `0x${base58ToHex(id).slice(6)}` +} diff --git a/packages/solhint-graph-config/README.md b/packages/solhint-graph-config/README.md new file mode 100644 index 000000000..7a724946b --- /dev/null +++ b/packages/solhint-graph-config/README.md @@ -0,0 +1,88 @@ +# solhint-graph-config + +This repository contains shared linting and formatting rules for Solidity projects. + +## Code linting + +### Installation + +⚠️ Unfortunately there isn't a way to install peer dependencies using Yarn v4, so we need to install them manually. + + +```bash +# Install with peer packages +yarn add --dev solhint solhint-graph-config + +# For projects on this monorepo +yarn add --dev solhint solhint-graph-config@workspace:^x.y.z +``` + +### Configuration + +Run `solhint` with `node_modules/solhint-graph-config/index.js` as the configuration file. We suggest creating an npm script to make it easier to run: + +```json + +{ + "scripts": { + "lint": "solhint --fix --noPrompt contracts/**/*.sol --config node_modules/solhint-graph-config/index.js" + } +} + +``` + +## Code formatting + +### Installation + +⚠️ Unfortunately there isn't a way to install peer dependencies using Yarn v4, so we need to install them manually. + + +```bash +# Install with peer packages +yarn add --dev solhint-graph-config prettier prettier-plugin-solidity + +# For projects on this monorepo +yarn add --dev solhint-graph-config@workspace:^x.y.z prettier prettier-plugin-solidity +``` + + +### Configuration: formatting + +Create a configuration file for prettier at `prettier.config.js`: + +```javascript +const prettierGraphConfig = require('solhint-graph-config/prettier') +module.exports = prettierGraphConfig +``` + +Running `prettier` will automatically pick up the configuration file. We suggest creating an npm script to make it easier to run: + +```json +{ + "scripts": { + "format": "prettier --write 'contracts/**/*.sol'" + } +} +``` + +## Tooling + +This package uses the following tools: +- [solhint](https://protofire.github.io/solhint/) as the base linting tool +- [prettier](https://prettier.io/) as the base formatting tool +- [prettier-plugin-solidity](https://github.com/prettier-solidity/prettier-plugin-solidity) to format Solidity code + + +## VSCode support + +If you are using VSCode you can install the [Solidity extension by Nomic Foundation](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity). Unfortunately there is currently no way of getting real-time linting output from solhint, but this extension will provide formatting support using our prettier config and will also provide inline code validation using solc compiler output. + +For formatting, the following settings should be added to your `settings.json` file: +```json + "[solidity]": { + "editor.defaultFormatter": "NomicFoundation.hardhat-solidity" + }, +``` + +Additionally you can configure the `Format document` keyboard shortcut to run `prettier --write` on demand. \ No newline at end of file diff --git a/packages/solhint-graph-config/index.js b/packages/solhint-graph-config/index.js new file mode 100644 index 000000000..b37be2810 --- /dev/null +++ b/packages/solhint-graph-config/index.js @@ -0,0 +1,12 @@ +module.exports = { + extends: 'solhint:recommended', + rules: { + 'func-visibility': ['warn', { ignoreConstructors: true }], + 'compiler-version': ['off'], + 'constructor-syntax': 'warn', + 'quotes': ['error', 'double'], + 'reason-string': ['off'], + 'not-rely-on-time': 'off', + 'no-empty-blocks': 'off', + }, +} diff --git a/packages/solhint-graph-config/package.json b/packages/solhint-graph-config/package.json new file mode 100644 index 000000000..2ead8bbef --- /dev/null +++ b/packages/solhint-graph-config/package.json @@ -0,0 +1,13 @@ +{ + "name": "solhint-graph-config", + "version": "0.0.1", + "description": "Linting and formatting rules for The Graph's Solidity projects", + "main": "index.js", + "author": "The Graph Team", + "license": "GPL-2.0-or-later", + "peerDependencies": { + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1", + "solhint": "^4.1.1" + } +} diff --git a/packages/solhint-graph-config/prettier.js b/packages/solhint-graph-config/prettier.js new file mode 100644 index 000000000..b7539ce04 --- /dev/null +++ b/packages/solhint-graph-config/prettier.js @@ -0,0 +1,15 @@ +module.exports = { + "printWidth": 120, + "useTabs": false, + "bracketSpacing": true, + "plugins": ["prettier-plugin-solidity"], + "overrides": [ + { + "files": "*.sol", + "options": { + "tabWidth": 4, + "singleQuote": false, + } + } + ] +} \ No newline at end of file diff --git a/packages/token-distribution/.env.sample b/packages/token-distribution/.env.sample new file mode 100644 index 000000000..1ecb4d424 --- /dev/null +++ b/packages/token-distribution/.env.sample @@ -0,0 +1,3 @@ +MNEMONIC= +ETHERSCAN_API_KEY= +INFURA_KEY= diff --git a/packages/token-distribution/.graphclientrc.yml b/packages/token-distribution/.graphclientrc.yml new file mode 100644 index 000000000..34d67cb06 --- /dev/null +++ b/packages/token-distribution/.graphclientrc.yml @@ -0,0 +1,21 @@ +sources: + - name: graph-network + handler: + graphql: + endpoint: https://api.thegraph.com/subgraphs/name/graphprotocol/graph-network-mainnet + retry: 5 + + - name: token-distribution + handler: + graphql: + endpoint: https://api.thegraph.com/subgraphs/name/graphprotocol/token-distribution + retry: 5 + transforms: + - autoPagination: + validateSchema: true + +documents: + - ops/queries/account.graphql + - ops/queries/curators.graphql + - ops/queries/network.graphql + - ops/queries/tokenLockWallets.graphql diff --git a/packages/token-distribution/.openzeppelin/goerli.json b/packages/token-distribution/.openzeppelin/goerli.json new file mode 100644 index 000000000..9429a5cae --- /dev/null +++ b/packages/token-distribution/.openzeppelin/goerli.json @@ -0,0 +1,135 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x4e8EC4059854d0634d7Ba04eA41B453cD56Afa5d", + "txHash": "0x47c8a0973f2457fda3f1243238d3b590cb78e6e78f2cd1040d97e94ced6834c4" + }, + "proxies": [ + { + "address": "0xa725CF32c367778CFF2ba7089Ab4e941BDD88612", + "txHash": "0x7297670fbbf9f1c014aac93fa0219522c079bdd0ad4bb16c75a204ba97b1bc81", + "kind": "transparent" + } + ], + "impls": { + "483bf2556291169f0be3d109cdfe83a3493b0312de77748f3926fc7426444bb5": { + "address": "0xF546bF936241571C380272bbf169D66D4184390c", + "txHash": "0xa276937f5f5913524ba900fa100509bfb3428e98e74f9f76345337c408c2614b", + "layout": { + "solcVersion": "0.7.3", + "storage": [ + { + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "Ownable", + "src": "contracts/Ownable.sol:19" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "Ownable", + "src": "contracts/Ownable.sol:22" + }, + { + "label": "_initialized", + "offset": 0, + "slot": "51", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:25" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "51", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:30" + }, + { + "label": "l2LockManager", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:50" + }, + { + "label": "l2WalletOwner", + "offset": 0, + "slot": "53", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:53" + }, + { + "label": "l2WalletAddress", + "offset": 0, + "slot": "54", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:56" + }, + { + "label": "tokenLockETHBalances", + "offset": 0, + "slot": "55", + "type": "t_mapping(t_address,t_uint256)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:59" + }, + { + "label": "l2Beneficiary", + "offset": 0, + "slot": "56", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:62" + }, + { + "label": "l2WalletAddressSetManually", + "offset": 0, + "slot": "57", + "type": "t_mapping(t_address,t_bool)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:66" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + } + } + } + } +} diff --git a/packages/token-distribution/.openzeppelin/mainnet.json b/packages/token-distribution/.openzeppelin/mainnet.json new file mode 100644 index 000000000..31ad4e83e --- /dev/null +++ b/packages/token-distribution/.openzeppelin/mainnet.json @@ -0,0 +1,135 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x79E321CB828A0D1435050a1ce8d7985C4C3dfFFA", + "txHash": "0x7ed23b9530cd24071011637e782f43e942b2e0206042a67f5efe3affddbbc9c8" + }, + "proxies": [ + { + "address": "0xCa82c7Ce3388b0B5d307574099aC57d7a00d509F", + "txHash": "0x8535f77828c04d09f10107dea149d9ad72b477a386fd482d109d456e487667e0", + "kind": "transparent" + } + ], + "impls": { + "81b972d1a45d53657aeda6174118a103da6ec0b7e74535dd83748f6618297656": { + "address": "0x6a2A9bAd7b9Fa6ecEE8f249a0850f47eE184a275", + "txHash": "0x5c0dea018da76739bc39d324588a3fdd87b35c86a28469eb1442f701af0a7a82", + "layout": { + "solcVersion": "0.7.3", + "storage": [ + { + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "Ownable", + "src": "contracts/Ownable.sol:19" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "Ownable", + "src": "contracts/Ownable.sol:22" + }, + { + "label": "_initialized", + "offset": 0, + "slot": "51", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:25" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "51", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:30" + }, + { + "label": "l2LockManager", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:50" + }, + { + "label": "l2WalletOwner", + "offset": 0, + "slot": "53", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:53" + }, + { + "label": "l2WalletAddress", + "offset": 0, + "slot": "54", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:56" + }, + { + "label": "tokenLockETHBalances", + "offset": 0, + "slot": "55", + "type": "t_mapping(t_address,t_uint256)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:59" + }, + { + "label": "l2Beneficiary", + "offset": 0, + "slot": "56", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:62" + }, + { + "label": "l2WalletAddressSetManually", + "offset": 0, + "slot": "57", + "type": "t_mapping(t_address,t_bool)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:66" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + } + } + } + } +} diff --git a/packages/token-distribution/.openzeppelin/unknown-11155111.json b/packages/token-distribution/.openzeppelin/unknown-11155111.json new file mode 100644 index 000000000..2257b3e49 --- /dev/null +++ b/packages/token-distribution/.openzeppelin/unknown-11155111.json @@ -0,0 +1,135 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0xBbfAaA4A754931757B925AC0DDCcf97EB08e2895", + "txHash": "0x39364dc94694446616735d46554b5b5a937a7ec904deffee7aec9e9213c6fc12" + }, + "proxies": [ + { + "address": "0x543F8BFFb65c46091B4eEF4b1c394dFa43C4b065", + "txHash": "0x73d09cc6f92b3c97de26d3049db72a41249e0772d45c24c3818bce3344de8070", + "kind": "transparent" + } + ], + "impls": { + "cd6b1adc749eb68d0f47e7a8ff7b7c183afb072ac1de568f0c8b991a4e6388d0": { + "address": "0xDB47924Ad61D5C64D7921E9D0cb049Fb404A2DFB", + "txHash": "0xcab1656794d9a5e19e396214c5a4a687dd7e1b48197237d6778001e5510bd70c", + "layout": { + "solcVersion": "0.7.3", + "storage": [ + { + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address", + "contract": "Ownable", + "src": "contracts/Ownable.sol:19" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "Ownable", + "src": "contracts/Ownable.sol:22" + }, + { + "label": "_initialized", + "offset": 0, + "slot": "51", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:25" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "51", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol:30" + }, + { + "label": "l2LockManager", + "offset": 0, + "slot": "52", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:50" + }, + { + "label": "l2WalletOwner", + "offset": 0, + "slot": "53", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:53" + }, + { + "label": "l2WalletAddress", + "offset": 0, + "slot": "54", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:56" + }, + { + "label": "tokenLockETHBalances", + "offset": 0, + "slot": "55", + "type": "t_mapping(t_address,t_uint256)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:59" + }, + { + "label": "l2Beneficiary", + "offset": 0, + "slot": "56", + "type": "t_mapping(t_address,t_address)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:62" + }, + { + "label": "l2WalletAddressSetManually", + "offset": 0, + "slot": "57", + "type": "t_mapping(t_address,t_bool)", + "contract": "L1GraphTokenLockTransferTool", + "src": "contracts/L1GraphTokenLockTransferTool.sol:66" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_uint256)": { + "label": "mapping(address => uint256)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + } + } + } + } +} diff --git a/packages/token-distribution/.openzeppelin/unknown-42161.json b/packages/token-distribution/.openzeppelin/unknown-42161.json new file mode 100644 index 000000000..b7de2438b --- /dev/null +++ b/packages/token-distribution/.openzeppelin/unknown-42161.json @@ -0,0 +1,25 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x69E5E6aae945d342d6FA17D112C137D18E52C4Af", + "txHash": "0x00dcd23252a58b8304af1019f0d34dfefee1199c4b809acbc382d13615aee939" + }, + "proxies": [ + { + "address": "0x23C9c8575E6bA0349a497b6D0E8F0b9239e68028", + "txHash": "0xecb5b61a0d6fbca8f01174fea87d34172d4321650ba0566b0a9c87c7eca8df73", + "kind": "transparent" + } + ], + "impls": { + "3dff628cbc1a793190dc5ae0bc979ad427a9a98001209a3664d22dafc301b9b1": { + "address": "0x440e07acE09d848a581077c6DC8D7fb60FD8af62", + "txHash": "0x19f4d4f2701765d612f8ec4d7703a3d84761c4d81f3822addea9ba7ed023e0b3", + "layout": { + "solcVersion": "0.7.3", + "storage": [], + "types": {} + } + } + } +} diff --git a/packages/token-distribution/.openzeppelin/unknown-421613.json b/packages/token-distribution/.openzeppelin/unknown-421613.json new file mode 100644 index 000000000..d76355128 --- /dev/null +++ b/packages/token-distribution/.openzeppelin/unknown-421613.json @@ -0,0 +1,25 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0x5de859Bfd66BC330950c7dbf77F7F8fE519a1834", + "txHash": "0xbc443c4f31a36a6ff2cb5a8f39d9debd530626f9f51a9acccf28db6cfb6e94e0" + }, + "proxies": [ + { + "address": "0xc1A9C2E76171e64Cd5669B3E89D9A25a6b0FAfB7", + "txHash": "0x4c0fdb3290d0e247de1d0863bc2a7b13ea9414a86e5bfe94f1e2eba7c5c47f70", + "kind": "transparent" + } + ], + "impls": { + "f6ef37a54af859f9b6df6f1932063a6236e85e4e6ef0d8873a358db6ba412cb5": { + "address": "0xDc95A3418B4869c09572141Db70344434C8Bd9a8", + "txHash": "0x4b3258ad891966098856994fb4b6fde4a156d275d3ad813daa4930b9fbcf7861", + "layout": { + "solcVersion": "0.7.3", + "storage": [], + "types": {} + } + } + } +} diff --git a/packages/token-distribution/.openzeppelin/unknown-421614.json b/packages/token-distribution/.openzeppelin/unknown-421614.json new file mode 100644 index 000000000..809238758 --- /dev/null +++ b/packages/token-distribution/.openzeppelin/unknown-421614.json @@ -0,0 +1,25 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0xaf06340Afd383c81C0F025806f93e613Bf6229b2", + "txHash": "0x9cae0d327af86d32826d828ce26eb50c3d7c1138a6591ceaebb2de5accef1fe5" + }, + "proxies": [ + { + "address": "0xe21cd62E1E0CD68476C47F518980226C0a05fB19", + "txHash": "0x4785cb6bfeae00d727ed1199ad2724772507d6631135c73797069382a58af7d3", + "kind": "transparent" + } + ], + "impls": { + "9473208ed72647e49559194b7e906bf5eeb9ed0daf880eefb020b9493100d856": { + "address": "0x435F557d1fa367CAF33B567589F22a911Be28957", + "txHash": "0x321a11019d5a3d8fbdf1ba435b4a7a9c1961f3a6178c8deb2aaaeaeae7515775", + "layout": { + "solcVersion": "0.7.3", + "storage": [], + "types": {} + } + } + } +} diff --git a/packages/token-distribution/.solcover.js b/packages/token-distribution/.solcover.js new file mode 100644 index 000000000..bef64bdf9 --- /dev/null +++ b/packages/token-distribution/.solcover.js @@ -0,0 +1,10 @@ +const skipFiles = [''] + +module.exports = { + providerOptions: { + mnemonic: 'myth like bonus scare over problem client lizard pioneer submit female collect', + network_id: 1337, + }, + skipFiles, + istanbulFolder: './reports/coverage', +} diff --git a/packages/token-distribution/DEPLOYMENT.md b/packages/token-distribution/DEPLOYMENT.md new file mode 100644 index 000000000..704333faf --- /dev/null +++ b/packages/token-distribution/DEPLOYMENT.md @@ -0,0 +1,151 @@ + + +## Deploy a TokenManager (L1) + +The following instructions are for testnet (goerli), use `--network mainnet` to deploy to Mainnet. + +### 1. Deploy a Token Manager contract + +During this process the master copy of the GraphTokenLockWallet will be deployed and used in the Manager. + +``` +npx hardhat deploy --tags manager --network goerli +``` + +### 2. Fund the manager with the amount we need to deploy contracts + +The task will convert the amount passed in GRT to wei before calling the contracts. + +``` +npx hardhat manager-deposit --amount --network goerli +``` + +### 3. Deploy a number of Token Lock contracts using the Manager + +The process to set up the CSV file is described in the [README](./README.md). + +``` +npx hardhat create-token-locks --deploy-file --result-file --owner-address --network goerli +``` + +### 4. Setup the Token Manager to allow default protocol functions + +``` +npx hardhat manager-setup-auth --target-address --network goerli +``` + +## Deploying the manager, wallet and transfer tools to L2 + +This assumes a manager and token lock have already been deployed in L1 (and potentially many managers and token locks). + +The following instructions are for testnet (goerli and Arbitrum goerli), use `--network mainnet` to deploy to Mainnet and `--network arbitrum-one` for Arbitrum One. + +### 1. Deploy the L2GraphTokenLockWallet master copy + +Keep in mind you might want to use a different mnemonic in `.env` for the L2 deployer. Note that each transfer tool in L1 will only support a single wallet implementation in L2, so if you deploy several L2 managers, make sure all of them use the same wallet master copy in L2. + +``` +npx hardhat deploy --tags l2-wallet --network arbitrum-goerli +``` + +### 2. Deploy the L1GraphTokenLockTransferTool + +You will be prompted for a few relevant addresses, including the Staking contract and the address of the L2GraphTokenLockWallet implementation that you just deployed. + +Note the transfer tool is upgradeable (uses an OZ transparent proxy). + +``` +npx hardhat deploy --tags l1-transfer-tool --network goerli +``` + +### 3. Deploy the L2GraphTokenLockManager for each L1 manager + +Note this will not ask you for the L1 manager address, it is set separately in the transfer tool contract. + +You can optionally fund the L2 manager if you'd like to also create L2-native vesting contracts with it. + +``` +npx hardhat deploy --tags l2-manager --network arbitrum-goerli +``` + +### 4. Deploy the L2GraphTokenLockTransferTool + +Note the transfer tool is upgradeable (uses an OZ transparent proxy). + +``` +npx hardhat deploy --tags l2-transfer-tool --network arbitrum-goerli +``` + +### 5. Set the L2 owners and manager addresses + +Each token lock has an owner, that may map to a different address in L2. So we need to set the owner address in the L1GraphTokenLockTransferTool. + +This is done using a hardhat console on L1, i.e. `npx hardhat console --network goerli`: + +```javascript +transferToolAddress = '' +l1Owner = '' +l2Owner = '' +deployer = (await hre.ethers.getSigners())[0] +transferTool = await hre.ethers.getContractAt('L1GraphTokenLockTransferTool', transferToolAddress) +await transferTool.connect(deployer).setL2WalletOwner(l1Owner, l2Owner) +// Repeat for each owner... +``` + +After doing this for each owner, you must also set the L2GraphTokenLockManager address that corresponds to each L1 manager: + +```javascript +transferToolAddress = '' +l1Manager = '' +l2Manager = '' +deployer = (await hre.ethers.getSigners())[0] +transferTool = await hre.ethers.getContractAt('L1GraphTokenLockTransferTool', transferToolAddress) +await transferTool.connect(deployer).setL2LockManager(l1Manager, l2Manager) +// Repeat for each manager... +``` + +### 6. Configure the new authorized functions in L1 + +The addition of the L1 transfer tool means adding a new authorized contract and functions in the L1 manager's allowlist. For each manager, we need to add a new token destination (the L1 transfer tool) and the corresponding functions. This assumes the deployer is also the manager owner, if that's not the case, use the correct signer: + +```javascript +transferToolAddress = '' +stakingAddress = ' +l1Manager = '' +deployer = (await hre.ethers.getSigners())[0] +tokenLockManager = await hre.ethers.getContractAt('GraphTokenLockManager', l1Manager) +await tokenLockManager.setAuthFunctionCall('depositToL2Locked(uint256,address,uint256,uint256,uint256)', transferToolAddress) +await tokenLockManager.setAuthFunctionCall('withdrawETH(address,uint256)', transferToolAddress) +await tokenLockManager.setAuthFunctionCall('setL2WalletAddressManually(address)', transferToolAddress) +await tokenLockManager.addTokenDestination(transferToolAddress) +await tokenLockManager.setAuthFunctionCall('transferLockedDelegationToL2(address,uint256,uint256,uint256)', stakingAddress) +await tokenLockManager.setAuthFunctionCall('transferLockedStakeToL2(uint256,uint256,uint256,uint256)', stakingAddress) +// Repeat for each manager... +``` + +Keep in mind that existing lock wallets that had already called `approveProtocol()` to interact with the protocol will need to call `revokeProtocol()` and then `approveProtocol()` to be able to use the transfer tool. + +### 7. Configure the authorized functions on L2 + +The L2 managers will also need to authorize the functions to interact with the protocol. This is similar to step 4 when setting up the manager in L1, but here we must specify the manager name used when deploying the L2 manager + +``` +npx hardhat manager-setup-auth --target-address --manager-name --network arbitrum-goerli +``` + +We then need to also add authorization to call the L2 transfer tool on a hardhat console: + +```javascript +transferToolAddress = '' +l2Manager = '' +deployer = (await hre.ethers.getSigners())[0] +tokenLockManager = await hre.ethers.getContractAt('L2GraphTokenLockManager', l2Manager) +await tokenLockManager.setAuthFunctionCall('withdrawToL1Locked(uint256)', transferToolAddress) +await tokenLockManager.addTokenDestination(transferToolAddress) +// Repeat for each manager... +``` + +### 8. Make sure the protocol is configured + +The contracts for The Graph must be configured such that the L1 transfer tool is added to the bridge callhook allowlist so that it can send data through the bridge. +Additionally, the L1Staking contract must be configured to use the L1 transfer tool when transferring stake and delegation for vesting contracts; this is done using the `setL1GraphTokenLockTransferTool` (called by the Governor, i.e. the Council). diff --git a/packages/token-distribution/LICENSE.md b/packages/token-distribution/LICENSE.md new file mode 100644 index 000000000..f417054d0 --- /dev/null +++ b/packages/token-distribution/LICENSE.md @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2020 The Graph Foundation. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/packages/token-distribution/README.md b/packages/token-distribution/README.md new file mode 100644 index 000000000..e4017294f --- /dev/null +++ b/packages/token-distribution/README.md @@ -0,0 +1,159 @@ +# Graph Protocol Token Lock + +This repository contains a number of contracts that will support the locking of tokens of participants under different schedules. +An important premise is that participants with locked tokens can perform a number of restricted actions in the protocol with their tokens. + +## Contracts + +### GraphTokenLock + +The contract lock manages a number of tokens deposited into the contract to ensure that they can only be released under certain time conditions. + +This contract implements a release scheduled based on periods where tokens are released in steps after each period ends. It can be configured with one period in which case it works like a plain TimeLock. +It also supports revocation by the contract owner to be used for vesting schedules. + +The contract supports receiving extra funds over the managed tokens that can be withdrawn by the beneficiary at any time. + +A releaseStartTime parameter is included to override the default release schedule and perform the first release on the configured time. After that initial release it will continue with the default schedule. + +### GraphTokenLockWallet + +This contract is built on top of the base **GraphTokenLock** functionality. It allows the use of locked funds only when authorized function calls are issued to the contract. +It works by "forwarding" authorized function calls to predefined target contracts in the Graph Network. + +The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. +The function calls allowed are queried to the **GraphTokenLockManager**, this way the same configuration can be shared for all the created lock wallet contracts. + +Locked tokens must only leave this contract under the locking rules and by the beneficiary calling release(). Tokens used in the protocol need to get back to this contract when unstaked or undelegated. + +Some users can profit by participating in the protocol through their locked tokens, if they withdraw them from the protocol back to the lock contract, they should be able to withdraw those surplus funds out of the contract. + +The following functions signatures will be authorized for use: + +``` +### Target + +- Staking contract address + + +### Function Signatures + +- setOperator(address,bool) + +- stake(uint256) +- unstake(uint256) +- withdraw() + +- setDelegationParameters(uint32,uint32,uint32) +- delegate(address,uint256) +- undelegate(address,uint256) +- withdrawDelegated(address,address) +``` + +### GraphTokenLockManager + +Contract that works as a factory of **GraphTokenLockWallet** contracts. It manages the function calls authorized to be called on any GraphTokenWallet and also holds addresses of our protocol contracts configured as targets. + +The Manager supports creating TokenLock contracts based on a mastercopy bytecode using a Minimal Proxy to save gas. It also do so with CREATE2 to have reproducible addresses, this way any future to be deployed contract address can be passed to beneficiaries before actual deployment. + +For convenience, the Manager will also fund the created contract with the amount of each contract's managed tokens. + +## L2 deployment and transfer tools + +As part of the process for The Graph to move to Arbitrum, some contracts were added to allow GraphTokenLockWallet beneficiaries to transfer their funds to a vesting wallet in L2 and transfer their stake and delegations to L2 as well, where they will be owned by the L2 vesting wallet. See [GIP-0046](https://forum.thegraph.com/t/gip-0046-l2-transfer-tools/4023) for more details about the architecture. + +### L2GraphTokenLockWallet + +The L2 version of the GraphTokenLockWallet is essentially the same, but adds a special function to initialize a wallet with information received from L1. Keep in mind that **vesting contracts in L2 that are created from an L1 contract cannot release funds in L2 until the end of the full vesting timeline**. Funds can be sent back to L1 using the L2GraphTokenLockTransferTool to be released there. + +### L2GraphTokenLockManager + +The L2 manager inherits from GraphTokenLockManager but includes an `onTokenTransfer` function for the GRT bridge to call when receiving locked GRT from L1. The first time that GRT is received for a new L1 wallet, the corresponding L2GraphTokenLockWallet contract is created and initialized. + +### L1GraphTokenLockTransferTool + +For L1 GraphTokenLockWallet beneficiaries to transfer to L2, they must use this transfer tool contract. The contract allows beneficiaries to deposit ETH to pay for the L2 gas and fees related to sending messages to L2. It then allows two different flows, depending on the state of the vesting contract: + +- For fully vested GraphTokenLockWallet contracts, the wallet can call the transfer tool specifying the address that the beneficiary wants to use in L2. This will be a normal wallet (can be an EOA or a multisig in L2), and this will be queried by the Staking contract when transferring stake or delegation. Please note that **this address can only be set once and cannot be changed**. +- For contracts that are still vesting, the wallet can call the transfer tool specifying an amount of GRT to transfer to L2. This GRT value will be sent from the vesting wallet's GRT balance, and must be nonzero. The caller can also specify a beneficiary that will own the L2 vesting wallet, which is only used if this hasn't already been set in a previous call. + +### L2GraphTokenLockTransferTool + +For beneficiaries of L1 vesting contracts to release funds that have been sent to L2, the GRT funds must be sent to L1 first. The L2GraphTokenLockTransferTool only has a `withdrawToL1Locked` function for this purpose, it will use the GRT bridge to send GRT to the L1 vesting contract that corresponds to the caller. + +## Operations + +For detailed instructions about deploying the manager or the transfer tools, check out [DEPLOYMENT.md](./DEPLOYMENT.md). + +### Deploying new vesting locks + +**1) Check configuration** + +Ensure the .env file contains the MNEMONIC you are going to use for the deployment. Please refer to the `.env.sample` file for reference. + +**2) Create the deployment file** + +The file must be have CSV format in placed in the `/ops` folder with the following header: +``` +beneficiary,managedAmount,startTime,endTime,periods,revocable,releaseStartTime,vestingCliffTime +... line 1 +... line 2 +... N +``` + +- **beneficiary** Address of the beneficiary of locked tokens. +- **managedAmount** Amount of tokens to be managed by the lock contract. +- **startTime** Start time of the release schedule. +- **endTime** End time of the release schedule. +- **periods** Number of periods between start time and end time. +- **revocable** Whether the contract is revocable. Should be 1 for `Enabled` or 2 for 1 `Disable`. Setting this to 0 for `NotSet` will cause the transaction to fail with error `Must set a revocability option`. +- **releaseStartTime** Override time for when the releases start. +- **vestingCliffTime** Time the cliff vests, 0 if no cliff + +You can define one line per contract. Keep the header in the file. + +In addition to that, create an empty file in the `/ops` folder to store the results of the deployed contracts. + +**2) Deposit funds in the Manager** + +You need to deposit enough funds in the Manager to be able to use for the deployments. When you run the `create-token-locks` command it will always check that the Manager has enough tokens to cover for the sum of vesting amount. + +``` +npx hardhat manager-deposit --amount --network +``` + +- **amount** is a string and it can have 18 decimals. For example 1000.12 + +- **network** depends on the `hardhat.config` but most of the times will be sepolia or mainnet. + +**3) Deploy the contracts** + +``` +npx hardhat create-token-locks --network sepolia \ + --deploy-file \ + --result-file \ + --owner-address \ + --dry-run (Flag) \ + --tx-builder (Flag) \ + --tx-builder-template (Optional) +``` + +- **network** depends on the hardhat.config but most of the times will be rinkeby or mainnet. + +- **deploy-file** file name under `/ops` that contains the contracts to deploy. + +- **result-file** file with the results of deployments. + +- **owner-address** address to use as owner of the vesting contracts. The owner can revoke the contract if revocable. + +- **dry-run** Get the deterministic contract addresses but do not deploy. + +- **tx-builder** Output transaction batch in JSON format, compatible with Gnosis Safe transaction builder. Does not deploy contracts. + +- **tx-builder-template** File to use as a template for the transaction builder. + +## Copyright + +Copyright © 2020 The Graph Foundation + +Licensed under the [MIT license](LICENSE.md). diff --git a/packages/token-distribution/abi/TokenLockWalletABIFull.json b/packages/token-distribution/abi/TokenLockWalletABIFull.json new file mode 100644 index 000000000..42f05c95a --- /dev/null +++ b/packages/token-distribution/abi/TokenLockWalletABIFull.json @@ -0,0 +1,773 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_allowed", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_destination", + "type": "address" + } + ], + "name": "setRewardsDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_indexingRewardCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_queryFeeCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_cooldownBlocks", + "type": "uint32" + } + ], + "name": "setDelegationParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_indexer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_indexer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_indexer", + "type": "address" + }, + { + "internalType": "address", + "name": "_delegateToIndexer", + "type": "address" + } + ], + "name": "withdrawDelegated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/token-distribution/abi/TokenLockWalletABIRemix.json b/packages/token-distribution/abi/TokenLockWalletABIRemix.json new file mode 100644 index 000000000..dc62b9d41 --- /dev/null +++ b/packages/token-distribution/abi/TokenLockWalletABIRemix.json @@ -0,0 +1,618 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "stake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "unstake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_allowed", + "type": "bool" + } + ], + "name": "setOperator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_destination", + "type": "address" + } + ], + "name": "setRewardsDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "_indexingRewardCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_queryFeeCut", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "_cooldownBlocks", + "type": "uint32" + } + ], + "name": "setDelegationParameters", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_indexer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokens", + "type": "uint256" + } + ], + "name": "delegate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_indexer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_shares", + "type": "uint256" + } + ], + "name": "undelegate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_indexer", + "type": "address" + }, + { + "internalType": "address", + "name": "_delegateToIndexer", + "type": "address" + } + ], + "name": "withdrawDelegated", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/packages/token-distribution/audits/2020-11-graph-token-distribution.pdf b/packages/token-distribution/audits/2020-11-graph-token-distribution.pdf new file mode 100644 index 000000000..cc11beb06 Binary files /dev/null and b/packages/token-distribution/audits/2020-11-graph-token-distribution.pdf differ diff --git a/packages/token-distribution/contracts/GraphTokenDistributor.sol b/packages/token-distribution/contracts/GraphTokenDistributor.sol new file mode 100644 index 000000000..a7cd88137 --- /dev/null +++ b/packages/token-distribution/contracts/GraphTokenDistributor.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +/** + * @title GraphTokenDistributor + * @dev Contract that allows distribution of tokens to multiple beneficiaries. + * The contract accept deposits in the configured token by anyone. + * The owner can setup the desired distribution by setting the amount of tokens + * assigned to each beneficiary account. + * Beneficiaries claim for their allocated tokens. + * Only the owner can withdraw tokens from this contract without limitations. + * For the distribution to work this contract must be unlocked by the owner. + */ +contract GraphTokenDistributor is Ownable { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + // -- State -- + + bool public locked; + mapping(address => uint256) public beneficiaries; + + IERC20 public token; + + // -- Events -- + + event BeneficiaryUpdated(address indexed beneficiary, uint256 amount); + event TokensDeposited(address indexed sender, uint256 amount); + event TokensWithdrawn(address indexed sender, uint256 amount); + event TokensClaimed(address indexed beneficiary, address to, uint256 amount); + event LockUpdated(bool locked); + + modifier whenNotLocked() { + require(locked == false, "Distributor: Claim is locked"); + _; + } + + /** + * Constructor. + * @param _token Token to use for deposits and withdrawals + */ + constructor(IERC20 _token) { + token = _token; + locked = true; + } + + /** + * Deposit tokens into the contract. + * Even if the ERC20 token can be transferred directly to the contract + * this function provide a safe interface to do the transfer and avoid mistakes + * @param _amount Amount to deposit + */ + function deposit(uint256 _amount) external { + token.safeTransferFrom(msg.sender, address(this), _amount); + emit TokensDeposited(msg.sender, _amount); + } + + // -- Admin functions -- + + /** + * Add token balance available for account. + * @param _account Address to assign tokens to + * @param _amount Amount of tokens to assign to beneficiary + */ + function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner { + _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount)); + } + + /** + * Add token balance available for multiple accounts. + * @param _accounts Addresses to assign tokens to + * @param _amounts Amounts of tokens to assign to beneficiary + */ + function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner { + require(_accounts.length == _amounts.length, "Distributor: !length"); + for (uint256 i = 0; i < _accounts.length; i++) { + _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i])); + } + } + + /** + * Remove token balance available for account. + * @param _account Address to assign tokens to + * @param _amount Amount of tokens to assign to beneficiary + */ + function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner { + _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount)); + } + + /** + * Remove token balance available for multiple accounts. + * @param _accounts Addresses to assign tokens to + * @param _amounts Amounts of tokens to assign to beneficiary + */ + function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner { + require(_accounts.length == _amounts.length, "Distributor: !length"); + for (uint256 i = 0; i < _accounts.length; i++) { + _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i])); + } + } + + /** + * Set amount of tokens available for beneficiary account. + * @param _account Address to assign tokens to + * @param _amount Amount of tokens to assign to beneficiary + */ + function _setBeneficiaryTokens(address _account, uint256 _amount) private { + require(_account != address(0), "Distributor: !account"); + + beneficiaries[_account] = _amount; + emit BeneficiaryUpdated(_account, _amount); + } + + /** + * Set locked withdrawals. + * @param _locked True to lock withdrawals + */ + function setLocked(bool _locked) external onlyOwner { + locked = _locked; + emit LockUpdated(_locked); + } + + /** + * Withdraw tokens from the contract. This function is included as + * a escape hatch in case of mistakes or to recover remaining funds. + * @param _amount Amount of tokens to withdraw + */ + function withdraw(uint256 _amount) external onlyOwner { + token.safeTransfer(msg.sender, _amount); + emit TokensWithdrawn(msg.sender, _amount); + } + + // -- Beneficiary functions -- + + /** + * Claim tokens and send to caller. + */ + function claim() external whenNotLocked { + claimTo(msg.sender); + } + + /** + * Claim tokens and send to address. + * @param _to Address where to send tokens + */ + function claimTo(address _to) public whenNotLocked { + uint256 claimableTokens = beneficiaries[msg.sender]; + require(claimableTokens > 0, "Distributor: Unavailable funds"); + + _setBeneficiaryTokens(msg.sender, 0); + + token.safeTransfer(_to, claimableTokens); + emit TokensClaimed(msg.sender, _to, claimableTokens); + } +} diff --git a/packages/token-distribution/contracts/GraphTokenLock.sol b/packages/token-distribution/contracts/GraphTokenLock.sol new file mode 100644 index 000000000..03cfbca43 --- /dev/null +++ b/packages/token-distribution/contracts/GraphTokenLock.sol @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import { Ownable as OwnableInitializable } from "./Ownable.sol"; +import "./MathUtils.sol"; +import "./IGraphTokenLock.sol"; + +/** + * @title GraphTokenLock + * @notice Contract that manages an unlocking schedule of tokens. + * @dev The contract lock manage a number of tokens deposited into the contract to ensure that + * they can only be released under certain time conditions. + * + * This contract implements a release scheduled based on periods and tokens are released in steps + * after each period ends. It can be configured with one period in which case it is like a plain TimeLock. + * It also supports revocation to be used for vesting schedules. + * + * The contract supports receiving extra funds than the managed tokens ones that can be + * withdrawn by the beneficiary at any time. + * + * A releaseStartTime parameter is included to override the default release schedule and + * perform the first release on the configured time. After that it will continue with the + * default schedule. + */ +abstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock { + using SafeMath for uint256; + using SafeERC20 for IERC20; + + uint256 private constant MIN_PERIOD = 1; + + // -- State -- + + IERC20 public token; + address public beneficiary; + + // Configuration + + // Amount of tokens managed by the contract schedule + uint256 public managedAmount; + + uint256 public startTime; // Start datetime (in unixtimestamp) + uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp) + uint256 public periods; // Number of vesting/release periods + + // First release date for tokens (in unixtimestamp) + // If set, no tokens will be released before releaseStartTime ignoring + // the amount to release each period + uint256 public releaseStartTime; + // A cliff set a date to which a beneficiary needs to get to vest + // all preceding periods + uint256 public vestingCliffTime; + Revocability public revocable; // Whether to use vesting for locked funds + + // State + + bool public isRevoked; + bool public isInitialized; + bool public isAccepted; + uint256 public releasedAmount; + uint256 public revokedAmount; + + // -- Events -- + + event TokensReleased(address indexed beneficiary, uint256 amount); + event TokensWithdrawn(address indexed beneficiary, uint256 amount); + event TokensRevoked(address indexed beneficiary, uint256 amount); + event BeneficiaryChanged(address newBeneficiary); + event LockAccepted(); + event LockCanceled(); + + /** + * @dev Only allow calls from the beneficiary of the contract + */ + modifier onlyBeneficiary() { + require(msg.sender == beneficiary, "!auth"); + _; + } + + /** + * @notice Initializes the contract + * @param _owner Address of the contract owner + * @param _beneficiary Address of the beneficiary of locked tokens + * @param _managedAmount Amount of tokens to be managed by the lock contract + * @param _startTime Start time of the release schedule + * @param _endTime End time of the release schedule + * @param _periods Number of periods between start time and end time + * @param _releaseStartTime Override time for when the releases start + * @param _vestingCliffTime Override time for when the vesting start + * @param _revocable Whether the contract is revocable + */ + function _initialize( + address _owner, + address _beneficiary, + address _token, + uint256 _managedAmount, + uint256 _startTime, + uint256 _endTime, + uint256 _periods, + uint256 _releaseStartTime, + uint256 _vestingCliffTime, + Revocability _revocable + ) internal { + require(!isInitialized, "Already initialized"); + require(_owner != address(0), "Owner cannot be zero"); + require(_beneficiary != address(0), "Beneficiary cannot be zero"); + require(_token != address(0), "Token cannot be zero"); + require(_managedAmount > 0, "Managed tokens cannot be zero"); + require(_startTime != 0, "Start time must be set"); + require(_startTime < _endTime, "Start time > end time"); + require(_periods >= MIN_PERIOD, "Periods cannot be below minimum"); + require(_revocable != Revocability.NotSet, "Must set a revocability option"); + require(_releaseStartTime < _endTime, "Release start time must be before end time"); + require(_vestingCliffTime < _endTime, "Cliff time must be before end time"); + + isInitialized = true; + + OwnableInitializable._initialize(_owner); + beneficiary = _beneficiary; + token = IERC20(_token); + + managedAmount = _managedAmount; + + startTime = _startTime; + endTime = _endTime; + periods = _periods; + + // Optionals + releaseStartTime = _releaseStartTime; + vestingCliffTime = _vestingCliffTime; + revocable = _revocable; + } + + /** + * @notice Change the beneficiary of funds managed by the contract + * @dev Can only be called by the beneficiary + * @param _newBeneficiary Address of the new beneficiary address + */ + function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary { + require(_newBeneficiary != address(0), "Empty beneficiary"); + beneficiary = _newBeneficiary; + emit BeneficiaryChanged(_newBeneficiary); + } + + /** + * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens + * @dev Can only be called by the beneficiary + */ + function acceptLock() external onlyBeneficiary { + isAccepted = true; + emit LockAccepted(); + } + + /** + * @notice Owner cancel the lock and return the balance in the contract + * @dev Can only be called by the owner + */ + function cancelLock() external onlyOwner { + require(isAccepted == false, "Cannot cancel accepted contract"); + + token.safeTransfer(owner(), currentBalance()); + + emit LockCanceled(); + } + + // -- Balances -- + + /** + * @notice Returns the amount of tokens currently held by the contract + * @return Tokens held in the contract + */ + function currentBalance() public view override returns (uint256) { + return token.balanceOf(address(this)); + } + + // -- Time & Periods -- + + /** + * @notice Returns the current block timestamp + * @return Current block timestamp + */ + function currentTime() public view override returns (uint256) { + return block.timestamp; + } + + /** + * @notice Gets duration of contract from start to end in seconds + * @return Amount of seconds from contract startTime to endTime + */ + function duration() public view override returns (uint256) { + return endTime.sub(startTime); + } + + /** + * @notice Gets time elapsed since the start of the contract + * @dev Returns zero if called before conctract starTime + * @return Seconds elapsed from contract startTime + */ + function sinceStartTime() public view override returns (uint256) { + uint256 current = currentTime(); + if (current <= startTime) { + return 0; + } + return current.sub(startTime); + } + + /** + * @notice Returns amount available to be released after each period according to schedule + * @return Amount of tokens available after each period + */ + function amountPerPeriod() public view override returns (uint256) { + return managedAmount.div(periods); + } + + /** + * @notice Returns the duration of each period in seconds + * @return Duration of each period in seconds + */ + function periodDuration() public view override returns (uint256) { + return duration().div(periods); + } + + /** + * @notice Gets the current period based on the schedule + * @return A number that represents the current period + */ + function currentPeriod() public view override returns (uint256) { + return sinceStartTime().div(periodDuration()).add(MIN_PERIOD); + } + + /** + * @notice Gets the number of periods that passed since the first period + * @return A number of periods that passed since the schedule started + */ + function passedPeriods() public view override returns (uint256) { + return currentPeriod().sub(MIN_PERIOD); + } + + // -- Locking & Release Schedule -- + + /** + * @notice Gets the currently available token according to the schedule + * @dev Implements the step-by-step schedule based on periods for available tokens + * @return Amount of tokens available according to the schedule + */ + function availableAmount() public view override returns (uint256) { + uint256 current = currentTime(); + + // Before contract start no funds are available + if (current < startTime) { + return 0; + } + + // After contract ended all funds are available + if (current > endTime) { + return managedAmount; + } + + // Get available amount based on period + return passedPeriods().mul(amountPerPeriod()); + } + + /** + * @notice Gets the amount of currently vested tokens + * @dev Similar to available amount, but is fully vested when contract is non-revocable + * @return Amount of tokens already vested + */ + function vestedAmount() public view override returns (uint256) { + // If non-revocable it is fully vested + if (revocable == Revocability.Disabled) { + return managedAmount; + } + + // Vesting cliff is activated and it has not passed means nothing is vested yet + if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) { + return 0; + } + + return availableAmount(); + } + + /** + * @notice Gets tokens currently available for release + * @dev Considers the schedule and takes into account already released tokens + * @return Amount of tokens ready to be released + */ + function releasableAmount() public view virtual override returns (uint256) { + // If a release start time is set no tokens are available for release before this date + // If not set it follows the default schedule and tokens are available on + // the first period passed + if (releaseStartTime > 0 && currentTime() < releaseStartTime) { + return 0; + } + + // Vesting cliff is activated and it has not passed means nothing is vested yet + // so funds cannot be released + if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) { + return 0; + } + + // A beneficiary can never have more releasable tokens than the contract balance + uint256 releasable = availableAmount().sub(releasedAmount); + return MathUtils.min(currentBalance(), releasable); + } + + /** + * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime + * @dev Does not consider schedule but just global amounts tracked + * @return Amount of outstanding tokens for the lifetime of the contract + */ + function totalOutstandingAmount() public view override returns (uint256) { + return managedAmount.sub(releasedAmount).sub(revokedAmount); + } + + /** + * @notice Gets surplus amount in the contract based on outstanding amount to release + * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. + * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be + * skewed, so the beneficiary might have to bridge back to L1 to release the surplus. + * @return Amount of tokens considered as surplus + */ + function surplusAmount() public view override returns (uint256) { + uint256 balance = currentBalance(); + uint256 outstandingAmount = totalOutstandingAmount(); + if (balance > outstandingAmount) { + return balance.sub(outstandingAmount); + } + return 0; + } + + // -- Value Transfer -- + + /** + * @notice Releases tokens based on the configured schedule + * @dev All available releasable tokens are transferred to beneficiary + */ + function release() external override onlyBeneficiary { + uint256 amountToRelease = releasableAmount(); + require(amountToRelease > 0, "No available releasable amount"); + + releasedAmount = releasedAmount.add(amountToRelease); + + token.safeTransfer(beneficiary, amountToRelease); + + emit TokensReleased(beneficiary, amountToRelease); + } + + /** + * @notice Withdraws surplus, unmanaged tokens from the contract + * @dev Tokens in the contract over outstanding amount are considered as surplus + * @param _amount Amount of tokens to withdraw + */ + function withdrawSurplus(uint256 _amount) external override onlyBeneficiary { + require(_amount > 0, "Amount cannot be zero"); + require(surplusAmount() >= _amount, "Amount requested > surplus available"); + + token.safeTransfer(beneficiary, _amount); + + emit TokensWithdrawn(beneficiary, _amount); + } + + /** + * @notice Revokes a vesting schedule and return the unvested tokens to the owner + * @dev Vesting schedule is always calculated based on managed tokens + */ + function revoke() external override onlyOwner { + require(revocable == Revocability.Enabled, "Contract is non-revocable"); + require(isRevoked == false, "Already revoked"); + + uint256 unvestedAmount = managedAmount.sub(vestedAmount()); + require(unvestedAmount > 0, "No available unvested amount"); + + revokedAmount = unvestedAmount; + isRevoked = true; + + token.safeTransfer(owner(), unvestedAmount); + + emit TokensRevoked(beneficiary, unvestedAmount); + } +} diff --git a/packages/token-distribution/contracts/GraphTokenLockManager.sol b/packages/token-distribution/contracts/GraphTokenLockManager.sol new file mode 100644 index 000000000..2ec96887e --- /dev/null +++ b/packages/token-distribution/contracts/GraphTokenLockManager.sol @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/utils/EnumerableSet.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +import "./MinimalProxyFactory.sol"; +import "./IGraphTokenLockManager.sol"; +import { GraphTokenLockWallet } from "./GraphTokenLockWallet.sol"; + +/** + * @title GraphTokenLockManager + * @notice This contract manages a list of authorized function calls and targets that can be called + * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. + * + * This contract receives funds to make the process of creating TokenLockWallet contracts + * easier by distributing them the initial tokens to be managed. + * + * The owner can setup a list of token destinations that will be used by TokenLock contracts to + * approve the pulling of funds, this way in can be guaranteed that only protocol contracts + * will manipulate users funds. + */ +contract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager { + using SafeERC20 for IERC20; + using EnumerableSet for EnumerableSet.AddressSet; + + // -- State -- + + mapping(bytes4 => address) public authFnCalls; + EnumerableSet.AddressSet private _tokenDestinations; + + address public masterCopy; + IERC20 internal _token; + + // -- Events -- + + event MasterCopyUpdated(address indexed masterCopy); + event TokenLockCreated( + address indexed contractAddress, + bytes32 indexed initHash, + address indexed beneficiary, + address token, + uint256 managedAmount, + uint256 startTime, + uint256 endTime, + uint256 periods, + uint256 releaseStartTime, + uint256 vestingCliffTime, + IGraphTokenLock.Revocability revocable + ); + + event TokensDeposited(address indexed sender, uint256 amount); + event TokensWithdrawn(address indexed sender, uint256 amount); + + event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature); + event TokenDestinationAllowed(address indexed dst, bool allowed); + + /** + * Constructor. + * @param _graphToken Token to use for deposits and withdrawals + * @param _masterCopy Address of the master copy to use to clone proxies + */ + constructor(IERC20 _graphToken, address _masterCopy) { + require(address(_graphToken) != address(0), "Token cannot be zero"); + _token = _graphToken; + setMasterCopy(_masterCopy); + } + + // -- Factory -- + + /** + * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts + * @param _masterCopy Address of contract bytecode to factory clone + */ + function setMasterCopy(address _masterCopy) public override onlyOwner { + require(_masterCopy != address(0), "MasterCopy cannot be zero"); + masterCopy = _masterCopy; + emit MasterCopyUpdated(_masterCopy); + } + + /** + * @notice Creates and fund a new token lock wallet using a minimum proxy + * @param _owner Address of the contract owner + * @param _beneficiary Address of the beneficiary of locked tokens + * @param _managedAmount Amount of tokens to be managed by the lock contract + * @param _startTime Start time of the release schedule + * @param _endTime End time of the release schedule + * @param _periods Number of periods between start time and end time + * @param _releaseStartTime Override time for when the releases start + * @param _revocable Whether the contract is revocable + */ + function createTokenLockWallet( + address _owner, + address _beneficiary, + uint256 _managedAmount, + uint256 _startTime, + uint256 _endTime, + uint256 _periods, + uint256 _releaseStartTime, + uint256 _vestingCliffTime, + IGraphTokenLock.Revocability _revocable + ) external override onlyOwner { + require(_token.balanceOf(address(this)) >= _managedAmount, "Not enough tokens to create lock"); + + // Create contract using a minimal proxy and call initializer + bytes memory initializer = abi.encodeWithSelector( + GraphTokenLockWallet.initialize.selector, + address(this), + _owner, + _beneficiary, + address(_token), + _managedAmount, + _startTime, + _endTime, + _periods, + _releaseStartTime, + _vestingCliffTime, + _revocable + ); + address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer); + + // Send managed amount to the created contract + _token.safeTransfer(contractAddress, _managedAmount); + + emit TokenLockCreated( + contractAddress, + keccak256(initializer), + _beneficiary, + address(_token), + _managedAmount, + _startTime, + _endTime, + _periods, + _releaseStartTime, + _vestingCliffTime, + _revocable + ); + } + + // -- Funds Management -- + + /** + * @notice Gets the GRT token address + * @return Token used for transfers and approvals + */ + function token() external view override returns (IERC20) { + return _token; + } + + /** + * @notice Deposits tokens into the contract + * @dev Even if the ERC20 token can be transferred directly to the contract + * this function provide a safe interface to do the transfer and avoid mistakes + * @param _amount Amount to deposit + */ + function deposit(uint256 _amount) external override { + require(_amount > 0, "Amount cannot be zero"); + _token.safeTransferFrom(msg.sender, address(this), _amount); + emit TokensDeposited(msg.sender, _amount); + } + + /** + * @notice Withdraws tokens from the contract + * @dev Escape hatch in case of mistakes or to recover remaining funds + * @param _amount Amount of tokens to withdraw + */ + function withdraw(uint256 _amount) external override onlyOwner { + require(_amount > 0, "Amount cannot be zero"); + _token.safeTransfer(msg.sender, _amount); + emit TokensWithdrawn(msg.sender, _amount); + } + + // -- Token Destinations -- + + /** + * @notice Adds an address that can be allowed by a token lock to pull funds + * @param _dst Destination address + */ + function addTokenDestination(address _dst) external override onlyOwner { + require(_dst != address(0), "Destination cannot be zero"); + require(_tokenDestinations.add(_dst), "Destination already added"); + emit TokenDestinationAllowed(_dst, true); + } + + /** + * @notice Removes an address that can be allowed by a token lock to pull funds + * @param _dst Destination address + */ + function removeTokenDestination(address _dst) external override onlyOwner { + require(_tokenDestinations.remove(_dst), "Destination already removed"); + emit TokenDestinationAllowed(_dst, false); + } + + /** + * @notice Returns True if the address is authorized to be a destination of tokens + * @param _dst Destination address + * @return True if authorized + */ + function isTokenDestination(address _dst) external view override returns (bool) { + return _tokenDestinations.contains(_dst); + } + + /** + * @notice Returns an array of authorized destination addresses + * @return Array of addresses authorized to pull funds from a token lock + */ + function getTokenDestinations() external view override returns (address[] memory) { + address[] memory dstList = new address[](_tokenDestinations.length()); + for (uint256 i = 0; i < _tokenDestinations.length(); i++) { + dstList[i] = _tokenDestinations.at(i); + } + return dstList; + } + + // -- Function Call Authorization -- + + /** + * @notice Sets an authorized function call to target + * @dev Input expected is the function signature as 'transfer(address,uint256)' + * @param _signature Function signature + * @param _target Address of the destination contract to call + */ + function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner { + _setAuthFunctionCall(_signature, _target); + } + + /** + * @notice Unsets an authorized function call to target + * @dev Input expected is the function signature as 'transfer(address,uint256)' + * @param _signature Function signature + */ + function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner { + bytes4 sigHash = _toFunctionSigHash(_signature); + authFnCalls[sigHash] = address(0); + + emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature); + } + + /** + * @notice Sets an authorized function call to target in bulk + * @dev Input expected is the function signature as 'transfer(address,uint256)' + * @param _signatures Function signatures + * @param _targets Address of the destination contract to call + */ + function setAuthFunctionCallMany( + string[] calldata _signatures, + address[] calldata _targets + ) external override onlyOwner { + require(_signatures.length == _targets.length, "Array length mismatch"); + + for (uint256 i = 0; i < _signatures.length; i++) { + _setAuthFunctionCall(_signatures[i], _targets[i]); + } + } + + /** + * @notice Sets an authorized function call to target + * @dev Input expected is the function signature as 'transfer(address,uint256)' + * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time + * @param _signature Function signature + * @param _target Address of the destination contract to call + */ + function _setAuthFunctionCall(string calldata _signature, address _target) internal { + require(_target != address(this), "Target must be other contract"); + require(Address.isContract(_target), "Target must be a contract"); + + bytes4 sigHash = _toFunctionSigHash(_signature); + authFnCalls[sigHash] = _target; + + emit FunctionCallAuth(msg.sender, sigHash, _target, _signature); + } + + /** + * @notice Gets the target contract to call for a particular function signature + * @param _sigHash Function signature hash + * @return Address of the target contract where to send the call + */ + function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) { + return authFnCalls[_sigHash]; + } + + /** + * @notice Returns true if the function call is authorized + * @param _sigHash Function signature hash + * @return True if authorized + */ + function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) { + return getAuthFunctionCallTarget(_sigHash) != address(0); + } + + /** + * @dev Converts a function signature string to 4-bytes hash + * @param _signature Function signature string + * @return Function signature hash + */ + function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) { + return _convertToBytes4(abi.encodeWithSignature(_signature)); + } + + /** + * @dev Converts function signature bytes to function signature hash (bytes4) + * @param _signature Function signature + * @return Function signature in bytes4 + */ + function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) { + require(_signature.length == 4, "Invalid method signature"); + bytes4 sigHash; + // solhint-disable-next-line no-inline-assembly + assembly { + sigHash := mload(add(_signature, 32)) + } + return sigHash; + } +} diff --git a/packages/token-distribution/contracts/GraphTokenLockSimple.sol b/packages/token-distribution/contracts/GraphTokenLockSimple.sol new file mode 100644 index 000000000..e5b00a3fa --- /dev/null +++ b/packages/token-distribution/contracts/GraphTokenLockSimple.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +import "./GraphTokenLock.sol"; + +/** + * @title GraphTokenLockSimple + * @notice This contract is the concrete simple implementation built on top of the base + * GraphTokenLock functionality for use when we only need the token lock schedule + * features but no interaction with the network. + * + * This contract is designed to be deployed without the use of a TokenManager. + */ +contract GraphTokenLockSimple is GraphTokenLock { + // Constructor + constructor() { + OwnableInitializable._initialize(msg.sender); + } + + // Initializer + function initialize( + address _owner, + address _beneficiary, + address _token, + uint256 _managedAmount, + uint256 _startTime, + uint256 _endTime, + uint256 _periods, + uint256 _releaseStartTime, + uint256 _vestingCliffTime, + Revocability _revocable + ) external onlyOwner { + _initialize( + _owner, + _beneficiary, + _token, + _managedAmount, + _startTime, + _endTime, + _periods, + _releaseStartTime, + _vestingCliffTime, + _revocable + ); + } +} diff --git a/packages/token-distribution/contracts/GraphTokenLockWallet.sol b/packages/token-distribution/contracts/GraphTokenLockWallet.sol new file mode 100644 index 000000000..3ac24cb13 --- /dev/null +++ b/packages/token-distribution/contracts/GraphTokenLockWallet.sol @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/utils/Address.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "./GraphTokenLock.sol"; +import "./IGraphTokenLockManager.sol"; + +/** + * @title GraphTokenLockWallet + * @notice This contract is built on top of the base GraphTokenLock functionality. + * It allows wallet beneficiaries to use the deposited funds to perform specific function calls + * on specific contracts. + * + * The idea is that supporters with locked tokens can participate in the protocol + * but disallow any release before the vesting/lock schedule. + * The beneficiary can issue authorized function calls to this contract that will + * get forwarded to a target contract. A target contract is any of our protocol contracts. + * The function calls allowed are queried to the GraphTokenLockManager, this way + * the same configuration can be shared for all the created lock wallet contracts. + * + * NOTE: Contracts used as target must have its function signatures checked to avoid collisions + * with any of this contract functions. + * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience + * the maximum amount of tokens is authorized. + * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT. + */ +contract GraphTokenLockWallet is GraphTokenLock { + using SafeMath for uint256; + + // -- State -- + + IGraphTokenLockManager public manager; + uint256 public usedAmount; + + // -- Events -- + + event ManagerUpdated(address indexed _oldManager, address indexed _newManager); + event TokenDestinationsApproved(); + event TokenDestinationsRevoked(); + + // Initializer + function initialize( + address _manager, + address _owner, + address _beneficiary, + address _token, + uint256 _managedAmount, + uint256 _startTime, + uint256 _endTime, + uint256 _periods, + uint256 _releaseStartTime, + uint256 _vestingCliffTime, + Revocability _revocable + ) external { + _initialize( + _owner, + _beneficiary, + _token, + _managedAmount, + _startTime, + _endTime, + _periods, + _releaseStartTime, + _vestingCliffTime, + _revocable + ); + _setManager(_manager); + } + + // -- Admin -- + + /** + * @notice Sets a new manager for this contract + * @param _newManager Address of the new manager + */ + function setManager(address _newManager) external onlyOwner { + _setManager(_newManager); + } + + /** + * @dev Sets a new manager for this contract + * @param _newManager Address of the new manager + */ + function _setManager(address _newManager) internal { + require(_newManager != address(0), "Manager cannot be empty"); + require(Address.isContract(_newManager), "Manager must be a contract"); + + address oldManager = address(manager); + manager = IGraphTokenLockManager(_newManager); + + emit ManagerUpdated(oldManager, _newManager); + } + + // -- Beneficiary -- + + /** + * @notice Approves protocol access of the tokens managed by this contract + * @dev Approves all token destinations registered in the manager to pull tokens + */ + function approveProtocol() external onlyBeneficiary { + address[] memory dstList = manager.getTokenDestinations(); + for (uint256 i = 0; i < dstList.length; i++) { + // Note this is only safe because we are using the max uint256 value + token.approve(dstList[i], type(uint256).max); + } + emit TokenDestinationsApproved(); + } + + /** + * @notice Revokes protocol access of the tokens managed by this contract + * @dev Revokes approval to all token destinations in the manager to pull tokens + */ + function revokeProtocol() external onlyBeneficiary { + address[] memory dstList = manager.getTokenDestinations(); + for (uint256 i = 0; i < dstList.length; i++) { + // Note this is only safe cause we're using 0 as the amount + token.approve(dstList[i], 0); + } + emit TokenDestinationsRevoked(); + } + + /** + * @notice Gets tokens currently available for release + * @dev Considers the schedule, takes into account already released tokens and used amount + * @return Amount of tokens ready to be released + */ + function releasableAmount() public view override returns (uint256) { + if (revocable == Revocability.Disabled) { + return super.releasableAmount(); + } + + // -- Revocability enabled logic + // This needs to deal with additional considerations for when tokens are used in the protocol + + // If a release start time is set no tokens are available for release before this date + // If not set it follows the default schedule and tokens are available on + // the first period passed + if (releaseStartTime > 0 && currentTime() < releaseStartTime) { + return 0; + } + + // Vesting cliff is activated and it has not passed means nothing is vested yet + // so funds cannot be released + if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) { + return 0; + } + + // A beneficiary can never have more releasable tokens than the contract balance + // We consider the `usedAmount` in the protocol as part of the calculations + // the beneficiary should not release funds that are used. + uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount); + return MathUtils.min(currentBalance(), releasable); + } + + /** + * @notice Forward authorized contract calls to protocol contracts + * @dev Fallback function can be called by the beneficiary only if function call is allowed + */ + // solhint-disable-next-line no-complex-fallback + fallback() external payable { + // Only beneficiary can forward calls + require(msg.sender == beneficiary, "Unauthorized caller"); + require(msg.value == 0, "ETH transfers not supported"); + + // Function call validation + address _target = manager.getAuthFunctionCallTarget(msg.sig); + require(_target != address(0), "Unauthorized function"); + + uint256 oldBalance = currentBalance(); + + // Call function with data + Address.functionCall(_target, msg.data); + + // Tracked used tokens in the protocol + // We do this check after balances were updated by the forwarded call + // Check is only enforced for revocable contracts to save some gas + if (revocable == Revocability.Enabled) { + // Track contract balance change + uint256 newBalance = currentBalance(); + if (newBalance < oldBalance) { + // Outflow + uint256 diff = oldBalance.sub(newBalance); + usedAmount = usedAmount.add(diff); + } else { + // Inflow: We can receive profits from the protocol, that could make usedAmount to + // underflow. We set it to zero in that case. + uint256 diff = newBalance.sub(oldBalance); + usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff); + } + require(usedAmount <= vestedAmount(), "Cannot use more tokens than vested amount"); + } + } + + /** + * @notice Receive function that always reverts. + * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159 + */ + receive() external payable { + revert("Bad call"); + } +} diff --git a/packages/token-distribution/contracts/ICallhookReceiver.sol b/packages/token-distribution/contracts/ICallhookReceiver.sol new file mode 100644 index 000000000..f8f01d56f --- /dev/null +++ b/packages/token-distribution/contracts/ICallhookReceiver.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +// Copied from graphprotocol/contracts, changed solidity version to 0.7.3 + +/** + * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge + * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must + * be allowlisted by the governor, but also implement this interface that contains + * the function that will actually be called by the L2GraphTokenGateway. + */ +pragma solidity ^0.7.3; + +interface ICallhookReceiver { + /** + * @notice Receive tokens with a callhook from the bridge + * @param _from Token sender in L1 + * @param _amount Amount of tokens that were transferred + * @param _data ABI-encoded callhook data + */ + function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external; +} diff --git a/packages/token-distribution/contracts/IGraphTokenLock.sol b/packages/token-distribution/contracts/IGraphTokenLock.sol new file mode 100644 index 000000000..eac89f414 --- /dev/null +++ b/packages/token-distribution/contracts/IGraphTokenLock.sol @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IGraphTokenLock { + enum Revocability { + NotSet, + Enabled, + Disabled + } + + // -- Balances -- + + function currentBalance() external view returns (uint256); + + // -- Time & Periods -- + + function currentTime() external view returns (uint256); + + function duration() external view returns (uint256); + + function sinceStartTime() external view returns (uint256); + + function amountPerPeriod() external view returns (uint256); + + function periodDuration() external view returns (uint256); + + function currentPeriod() external view returns (uint256); + + function passedPeriods() external view returns (uint256); + + // -- Locking & Release Schedule -- + + function availableAmount() external view returns (uint256); + + function vestedAmount() external view returns (uint256); + + function releasableAmount() external view returns (uint256); + + function totalOutstandingAmount() external view returns (uint256); + + function surplusAmount() external view returns (uint256); + + // -- Value Transfer -- + + function release() external; + + function withdrawSurplus(uint256 _amount) external; + + function revoke() external; +} diff --git a/packages/token-distribution/contracts/IGraphTokenLockManager.sol b/packages/token-distribution/contracts/IGraphTokenLockManager.sol new file mode 100644 index 000000000..c646e5e16 --- /dev/null +++ b/packages/token-distribution/contracts/IGraphTokenLockManager.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "./IGraphTokenLock.sol"; + +interface IGraphTokenLockManager { + // -- Factory -- + + function setMasterCopy(address _masterCopy) external; + + function createTokenLockWallet( + address _owner, + address _beneficiary, + uint256 _managedAmount, + uint256 _startTime, + uint256 _endTime, + uint256 _periods, + uint256 _releaseStartTime, + uint256 _vestingCliffTime, + IGraphTokenLock.Revocability _revocable + ) external; + + // -- Funds Management -- + + function token() external returns (IERC20); + + function deposit(uint256 _amount) external; + + function withdraw(uint256 _amount) external; + + // -- Allowed Funds Destinations -- + + function addTokenDestination(address _dst) external; + + function removeTokenDestination(address _dst) external; + + function isTokenDestination(address _dst) external view returns (bool); + + function getTokenDestinations() external view returns (address[] memory); + + // -- Function Call Authorization -- + + function setAuthFunctionCall(string calldata _signature, address _target) external; + + function unsetAuthFunctionCall(string calldata _signature) external; + + function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external; + + function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address); + + function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool); +} diff --git a/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol b/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol new file mode 100644 index 000000000..962cf54ee --- /dev/null +++ b/packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol @@ -0,0 +1,319 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import { AddressUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol"; +import { ITokenGateway } from "./arbitrum/ITokenGateway.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { L2GraphTokenLockManager } from "./L2GraphTokenLockManager.sol"; +import { GraphTokenLockWallet } from "./GraphTokenLockWallet.sol"; +import { MinimalProxyFactory } from "./MinimalProxyFactory.sol"; +import { IGraphTokenLock } from "./IGraphTokenLock.sol"; +import { Ownable as OwnableInitializable } from "./Ownable.sol"; +import { SafeMathUpgradeable } from "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; + +/** + * @title L1GraphTokenLockTransferTool contract + * @notice This contract is used to transfer GRT from GraphTokenLockWallets + * to a counterpart on L2. It is deployed on L1 and will send the GRT through + * the L1GraphTokenGateway with a callhook to the L2GraphTokenLockManager, including + * data to create a L2GraphTokenLockWallet on L2. + * + * Note that the L2GraphTokenLockWallet will not allow releasing any GRT until the end of + * the vesting timeline, but will allow sending the GRT back to the L1 wallet. + * + * Beneficiaries for a GraphTokenLockWallet can perform the depositToL2Locked call + * as many times as they want, and the GRT will be sent to the same L2GraphTokenLockWallet. + * + * Since all retryable tickets to send transactions to L2 require ETH for gas, this + * contract also allows users to deposit ETH to be used for gas on L2, both for + * the depositToL2Locked calls and for the transfer tools in the Staking contract for + * The Graph. + * + * See GIP-0046 for more details: https://forum.thegraph.com/t/4023 + */ +contract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, MinimalProxyFactory { + using SafeMathUpgradeable for uint256; + + /// Address of the L1 GRT token contract + IERC20 public immutable graphToken; + /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses + address public immutable l2Implementation; + /// Address of the L1GraphTokenGateway contract + ITokenGateway public immutable l1Gateway; + /// Address of the Staking contract, used to pull ETH for L2 ticket gas + address payable public immutable staking; + /// L2 lock manager for each L1 lock manager. + /// L1 GraphTokenLockManager => L2GraphTokenLockManager + mapping(address => address) public l2LockManager; + /// L2 wallet owner for each L1 wallet owner. + /// L1 wallet owner => L2 wallet owner + mapping(address => address) public l2WalletOwner; + /// L2 wallet address for each L1 wallet address. + /// L1 wallet => L2 wallet + mapping(address => address) public l2WalletAddress; + /// ETH balance from each token lock, used to pay for L2 gas: + /// L1 wallet address => ETH balance + mapping(address => uint256) public tokenLockETHBalances; + /// L2 beneficiary corresponding to each L1 wallet address. + /// L1 wallet => L2 beneficiary + mapping(address => address) public l2Beneficiary; + /// Indicates whether an L2 wallet address for a wallet + /// has been set manually, in which case it can't call depositToL2Locked. + /// L1 wallet => bool + mapping(address => bool) public l2WalletAddressSetManually; + + /// @dev Emitted when the L2 lock manager for an L1 lock manager is set + event L2LockManagerSet(address indexed l1LockManager, address indexed l2LockManager); + /// @dev Emitted when the L2 wallet owner for an L1 wallet owner is set + event L2WalletOwnerSet(address indexed l1WalletOwner, address indexed l2WalletOwner); + /// @dev Emitted when GRT is sent to L2 from a token lock + event LockedFundsSentToL2( + address indexed l1Wallet, + address indexed l2Wallet, + address indexed l1LockManager, + address l2LockManager, + uint256 amount + ); + /// @dev Emitted when an L2 wallet address is set for an L1 wallet + event L2WalletAddressSet(address indexed l1Wallet, address indexed l2Wallet); + /// @dev Emitted when ETH is deposited to a token lock's account + event ETHDeposited(address indexed tokenLock, uint256 amount); + /// @dev Emitted when ETH is withdrawn from a token lock's account + event ETHWithdrawn(address indexed tokenLock, address indexed destination, uint256 amount); + /// @dev Emitted when ETH is pulled from a token lock's account by Staking or this tool to pay for an L2 ticket + event ETHPulled(address indexed tokenLock, uint256 amount); + /// @dev Emitted when the L2 beneficiary for a partially vested L1 lock is set + event L2BeneficiarySet(address indexed l1Wallet, address indexed l2Beneficiary); + + /** + * @notice Construct a new L1GraphTokenLockTransferTool contract + * @dev The deployer of the contract will become its owner. + * Note this contract is meant to be deployed behind a transparent proxy, + * so this will run at the implementation's storage context; it will set + * immutable variables and make the implementation be owned by the deployer. + * @param _graphToken Address of the L1 GRT token contract + * @param _l2Implementation Address of the L2GraphTokenLockWallet implementation in L2 + * @param _l1Gateway Address of the L1GraphTokenGateway contract + * @param _staking Address of the Staking contract + */ + constructor( + IERC20 _graphToken, + address _l2Implementation, + ITokenGateway _l1Gateway, + address payable _staking + ) initializer { + OwnableInitializable._initialize(msg.sender); + graphToken = _graphToken; + l2Implementation = _l2Implementation; + l1Gateway = _l1Gateway; + staking = _staking; + } + + /** + * @notice Initialize the L1GraphTokenLockTransferTool contract + * @dev This function will run in the proxy's storage context, so it will + * set the owner of the proxy contract which can be different from the implementation owner. + * @param _owner Address of the owner of the L1GraphTokenLockTransferTool contract + */ + function initialize(address _owner) external initializer { + OwnableInitializable._initialize(_owner); + } + + /** + * @notice Set the L2 lock manager that corresponds to an L1 lock manager + * @param _l1LockManager Address of the L1 lock manager + * @param _l2LockManager Address of the L2 lock manager (in L2) + */ + function setL2LockManager(address _l1LockManager, address _l2LockManager) external onlyOwner { + l2LockManager[_l1LockManager] = _l2LockManager; + emit L2LockManagerSet(_l1LockManager, _l2LockManager); + } + + /** + * @notice Set the L2 wallet owner that corresponds to an L1 wallet owner + * @param _l1WalletOwner Address of the L1 wallet owner + * @param _l2WalletOwner Address of the L2 wallet owner (in L2) + */ + function setL2WalletOwner(address _l1WalletOwner, address _l2WalletOwner) external onlyOwner { + l2WalletOwner[_l1WalletOwner] = _l2WalletOwner; + emit L2WalletOwnerSet(_l1WalletOwner, _l2WalletOwner); + } + + /** + * @notice Deposit ETH on a token lock's account, to be used for L2 retryable ticket gas. + * This function can be called by anyone, but the ETH will be credited to the token lock. + * DO NOT try to call this through the token lock, as locks do not forward ETH value (and the + * function call should not be allowlisted). + * @param _tokenLock Address of the L1 GraphTokenLockWallet that will own the ETH + */ + function depositETH(address _tokenLock) external payable { + tokenLockETHBalances[_tokenLock] = tokenLockETHBalances[_tokenLock].add(msg.value); + emit ETHDeposited(_tokenLock, msg.value); + } + + /** + * @notice Withdraw ETH from a token lock's account. + * This function must be called from the token lock contract, but the destination + * _must_ be a different address, as any ETH sent to the token lock would otherwise be + * lost. + * @param _destination Address to send the ETH + * @param _amount Amount of ETH to send + */ + function withdrawETH(address _destination, uint256 _amount) external { + require(_amount > 0, "INVALID_AMOUNT"); + // We can't send eth to a token lock or it will be stuck + require(msg.sender != _destination, "INVALID_DESTINATION"); + require(tokenLockETHBalances[msg.sender] >= _amount, "INSUFFICIENT_BALANCE"); + tokenLockETHBalances[msg.sender] -= _amount; + // solhint-disable-next-line avoid-low-level-calls + (bool success, ) = payable(_destination).call{ value: _amount }(""); + require(success, "TRANSFER_FAILED"); + emit ETHWithdrawn(msg.sender, _destination, _amount); + } + + /** + * @notice Pull ETH from a token lock's account, to be used for L2 retryable ticket gas. + * This can only be called by the Staking contract. + * @param _tokenLock GraphTokenLockWallet that owns the ETH that will be debited + * @param _amount Amount of ETH to pull + */ + function pullETH(address _tokenLock, uint256 _amount) external { + require(msg.sender == staking, "ONLY_STAKING"); + require(tokenLockETHBalances[_tokenLock] >= _amount, "INSUFFICIENT_BALANCE"); + tokenLockETHBalances[_tokenLock] -= _amount; + // solhint-disable-next-line avoid-low-level-calls + (bool success, ) = staking.call{ value: _amount }(""); + require(success, "TRANSFER_FAILED"); + emit ETHPulled(_tokenLock, _amount); + } + + /** + * @notice Deposit GRT to L2, from a token lock in L1 to a token lock in L2. + * If the token lock in L2 does not exist, it will be created when the message is received + * by the L2GraphTokenLockManager. + * Before calling this (which must be done through the token lock wallet), make sure + * there is enough ETH in the token lock's account to cover the L2 retryable ticket gas. + * Note that L2 submission fee and gas refunds will be lost. + * You can add ETH to the token lock's account by calling depositETH(). + * Note that after calling this, you will NOT be able to use setL2WalletAddressManually() to + * set an L2 wallet address, as the L2 wallet address will be set automatically when the + * message is received by the L2GraphTokenLockManager. + * @dev The gas parameters for L2 can be estimated using the Arbitrum SDK. + * @param _amount Amount of GRT to deposit + * @param _l2Beneficiary Address of the beneficiary for the token lock in L2. Must be the same for subsequent calls of this function, and not an L1 contract. + * @param _maxGas Maximum gas to use for the L2 retryable ticket + * @param _gasPriceBid Gas price to use for the L2 retryable ticket + * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket + */ + function depositToL2Locked( + uint256 _amount, + address _l2Beneficiary, + uint256 _maxGas, + uint256 _gasPriceBid, + uint256 _maxSubmissionCost + ) external { + // Check that msg.sender is a GraphTokenLockWallet + // That uses GRT and has a corresponding manager set in L2. + GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender); + require(wallet.token() == graphToken, "INVALID_TOKEN"); + address l1Manager = address(wallet.manager()); + address l2Manager = l2LockManager[l1Manager]; + require(l2Manager != address(0), "INVALID_MANAGER"); + require(wallet.isInitialized(), "!INITIALIZED"); + require(wallet.revocable() != IGraphTokenLock.Revocability.Enabled, "REVOCABLE"); + require(_amount <= graphToken.balanceOf(msg.sender), "INSUFFICIENT_BALANCE"); + require(_amount != 0, "ZERO_AMOUNT"); + + if (l2Beneficiary[msg.sender] == address(0)) { + require(_l2Beneficiary != address(0), "INVALID_BENEFICIARY_ZERO"); + require(!AddressUpgradeable.isContract(_l2Beneficiary), "INVALID_BENEFICIARY_CONTRACT"); + l2Beneficiary[msg.sender] = _l2Beneficiary; + emit L2BeneficiarySet(msg.sender, _l2Beneficiary); + } else { + require(l2Beneficiary[msg.sender] == _l2Beneficiary, "INVALID_BENEFICIARY"); + } + + uint256 expectedEth = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid)); + require(tokenLockETHBalances[msg.sender] >= expectedEth, "INSUFFICIENT_ETH_BALANCE"); + tokenLockETHBalances[msg.sender] -= expectedEth; + + bytes memory encodedData; + { + address l2Owner = l2WalletOwner[wallet.owner()]; + require(l2Owner != address(0), "L2_OWNER_NOT_SET"); + // Extract all the storage variables from the GraphTokenLockWallet + L2GraphTokenLockManager.TransferredWalletData memory data = L2GraphTokenLockManager.TransferredWalletData({ + l1Address: msg.sender, + owner: l2Owner, + beneficiary: l2Beneficiary[msg.sender], + managedAmount: wallet.managedAmount(), + startTime: wallet.startTime(), + endTime: wallet.endTime() + }); + encodedData = abi.encode(data); + } + + if (l2WalletAddress[msg.sender] == address(0)) { + require(wallet.endTime() >= block.timestamp, "FULLY_VESTED_USE_MANUAL_ADDRESS"); + address newAddress = getDeploymentAddress(keccak256(encodedData), l2Implementation, l2Manager); + l2WalletAddress[msg.sender] = newAddress; + emit L2WalletAddressSet(msg.sender, newAddress); + } else { + require(!l2WalletAddressSetManually[msg.sender], "CANT_DEPOSIT_TO_MANUAL_ADDRESS"); + } + + graphToken.transferFrom(msg.sender, address(this), _amount); + + // Send the tokens with a message through the L1GraphTokenGateway to the L2GraphTokenLockManager + graphToken.approve(address(l1Gateway), _amount); + { + bytes memory transferData = abi.encode(_maxSubmissionCost, encodedData); + l1Gateway.outboundTransfer{ value: expectedEth }( + address(graphToken), + l2Manager, + _amount, + _maxGas, + _gasPriceBid, + transferData + ); + } + emit ETHPulled(msg.sender, expectedEth); + emit LockedFundsSentToL2(msg.sender, l2WalletAddress[msg.sender], l1Manager, l2Manager, _amount); + } + + /** + * @notice Manually set the L2 wallet address for a token lock in L1. + * This will only work for token locks that have not been initialized in L2 yet, and + * that are fully vested (endTime < current timestamp). + * This address can then be used to send stake or delegation to L2 on the Staking contract. + * After calling this, the vesting lock will NOT be allowed to use depositToL2Locked + * to send GRT to L2, the beneficiary must withdraw the tokens and bridge them manually. + * @param _l2Wallet Address of the L2 wallet + */ + function setL2WalletAddressManually(address _l2Wallet) external { + // Check that msg.sender is a GraphTokenLockWallet + // That uses GRT and has a corresponding manager set in L2. + GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender); + require(wallet.token() == graphToken, "INVALID_TOKEN"); + address l1Manager = address(wallet.manager()); + address l2Manager = l2LockManager[l1Manager]; + require(l2Manager != address(0), "INVALID_MANAGER"); + require(wallet.isInitialized(), "!INITIALIZED"); + + // Check that the wallet is fully vested + require(wallet.endTime() < block.timestamp, "NOT_FULLY_VESTED"); + + // Check that the wallet has not set an L2 wallet yet + require(l2WalletAddress[msg.sender] == address(0), "L2_WALLET_ALREADY_SET"); + + // Check that the L2 address is not zero + require(_l2Wallet != address(0), "ZERO_ADDRESS"); + // Set the L2 wallet address + l2WalletAddress[msg.sender] = _l2Wallet; + l2WalletAddressSetManually[msg.sender] = true; + emit L2WalletAddressSet(msg.sender, _l2Wallet); + } +} diff --git a/packages/token-distribution/contracts/L2GraphTokenLockManager.sol b/packages/token-distribution/contracts/L2GraphTokenLockManager.sol new file mode 100644 index 000000000..ee1c30a59 --- /dev/null +++ b/packages/token-distribution/contracts/L2GraphTokenLockManager.sol @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; + +import { ICallhookReceiver } from "./ICallhookReceiver.sol"; +import { GraphTokenLockManager } from "./GraphTokenLockManager.sol"; +import { L2GraphTokenLockWallet } from "./L2GraphTokenLockWallet.sol"; + +/** + * @title L2GraphTokenLockManager + * @notice This contract manages a list of authorized function calls and targets that can be called + * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. + * + * This contract receives funds to make the process of creating TokenLockWallet contracts + * easier by distributing them the initial tokens to be managed. + * + * In particular, this L2 variant is designed to receive token lock wallets from L1, + * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until + * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using + * the L2GraphTokenLockTransferTool contract. + * + * The owner can setup a list of token destinations that will be used by TokenLock contracts to + * approve the pulling of funds, this way in can be guaranteed that only protocol contracts + * will manipulate users funds. + */ +contract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver { + using SafeERC20 for IERC20; + + /// @dev Struct to hold the data of a transferred wallet; this is + /// the data that must be encoded in L1 to send a wallet to L2. + struct TransferredWalletData { + address l1Address; + address owner; + address beneficiary; + uint256 managedAmount; + uint256 startTime; + uint256 endTime; + } + + /// Address of the L2GraphTokenGateway + address public immutable l2Gateway; + /// Address of the L1 transfer tool contract (in L1, no aliasing) + address public immutable l1TransferTool; + /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) + /// L1 address => L2 address + mapping(address => address) public l1WalletToL2Wallet; + /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) + /// L2 address => L1 address + mapping(address => address) public l2WalletToL1Wallet; + + /// @dev Event emitted when a wallet is received and created from L1 + event TokenLockCreatedFromL1( + address indexed contractAddress, + bytes32 initHash, + address indexed beneficiary, + uint256 managedAmount, + uint256 startTime, + uint256 endTime, + address indexed l1Address + ); + + /// @dev Emitted when locked tokens are received from L1 (whether the wallet + /// had already been received or not) + event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount); + + /** + * @dev Checks that the sender is the L2GraphTokenGateway. + */ + modifier onlyL2Gateway() { + require(msg.sender == l2Gateway, "ONLY_GATEWAY"); + _; + } + + /** + * @notice Constructor for the L2GraphTokenLockManager contract. + * @param _graphToken Address of the L2 GRT token contract + * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation + * @param _l2Gateway Address of the L2GraphTokenGateway contract + * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing) + */ + constructor( + IERC20 _graphToken, + address _masterCopy, + address _l2Gateway, + address _l1TransferTool + ) GraphTokenLockManager(_graphToken, _masterCopy) { + l2Gateway = _l2Gateway; + l1TransferTool = _l1TransferTool; + } + + /** + * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1. + * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to + * the existing wallet if it does. + * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool + * @param _amount Amount of tokens received + * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct + */ + function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway { + require(_from == l1TransferTool, "ONLY_TRANSFER_TOOL"); + TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData)); + + if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) { + // If the wallet was already received, just send the tokens to the L2 address + _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount); + } else { + // Create contract using a minimal proxy and call initializer + (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData); + l1WalletToL2Wallet[walletData.l1Address] = contractAddress; + l2WalletToL1Wallet[contractAddress] = walletData.l1Address; + + // Send managed amount to the created contract + _token.safeTransfer(contractAddress, _amount); + + emit TokenLockCreatedFromL1( + contractAddress, + initHash, + walletData.beneficiary, + walletData.managedAmount, + walletData.startTime, + walletData.endTime, + walletData.l1Address + ); + } + emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount); + } + + /** + * @dev Deploy a token lock wallet with data received from L1 + * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data + * @param _walletData Data of the wallet to be created + * @return Hash of the initialization calldata + * @return Address of the created contract + */ + function _deployFromL1( + bytes32 _salt, + TransferredWalletData memory _walletData + ) internal returns (bytes32, address) { + bytes memory initializer = _encodeInitializer(_walletData); + address contractAddress = _deployProxy2(_salt, masterCopy, initializer); + return (keccak256(initializer), contractAddress); + } + + /** + * @dev Encode the initializer for the token lock wallet received from L1 + * @param _walletData Data of the wallet to be created + * @return Encoded initializer calldata, including the function signature + */ + function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) { + return + abi.encodeWithSelector( + L2GraphTokenLockWallet.initializeFromL1.selector, + address(this), + address(_token), + _walletData + ); + } +} diff --git a/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol b/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol new file mode 100644 index 000000000..01010a3a0 --- /dev/null +++ b/packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import { L2GraphTokenLockManager } from "./L2GraphTokenLockManager.sol"; +import { L2GraphTokenLockWallet } from "./L2GraphTokenLockWallet.sol"; +import { ITokenGateway } from "./arbitrum/ITokenGateway.sol"; + +/** + * @title L2GraphTokenLockTransferTool contract + * @notice This contract is used to transfer GRT from L2 token lock wallets + * back to their L1 counterparts. + */ +contract L2GraphTokenLockTransferTool { + /// Address of the L2 GRT token + IERC20 public immutable graphToken; + /// Address of the L2GraphTokenGateway + ITokenGateway public immutable l2Gateway; + /// Address of the L1 GRT token (in L1, no aliasing) + address public immutable l1GraphToken; + + /// @dev Emitted when GRT is sent to L1 from a token lock + event LockedFundsSentToL1( + address indexed l1Wallet, + address indexed l2Wallet, + address indexed l2LockManager, + uint256 amount + ); + + /** + * @notice Constructor for the L2GraphTokenLockTransferTool contract + * @dev Note the L2GraphTokenLockTransferTool can be deployed behind a proxy, + * and the constructor for the implementation will only set some immutable + * variables. + * @param _graphToken Address of the L2 GRT token + * @param _l2Gateway Address of the L2GraphTokenGateway + * @param _l1GraphToken Address of the L1 GRT token (in L1, no aliasing) + */ + constructor(IERC20 _graphToken, ITokenGateway _l2Gateway, address _l1GraphToken) { + graphToken = _graphToken; + l2Gateway = _l2Gateway; + l1GraphToken = _l1GraphToken; + } + + /** + * @notice Withdraw GRT from an L2 token lock wallet to its L1 counterpart. + * This function must be called from an L2GraphTokenLockWallet contract. + * The GRT will be sent to L1 and must be claimed using the Arbitrum Outbox on L1 + * after the standard Arbitrum withdrawal period (7 days). + * @param _amount Amount of GRT to withdraw + */ + function withdrawToL1Locked(uint256 _amount) external { + L2GraphTokenLockWallet wallet = L2GraphTokenLockWallet(msg.sender); + L2GraphTokenLockManager manager = L2GraphTokenLockManager(address(wallet.manager())); + require(address(manager) != address(0), "INVALID_SENDER"); + address l1Wallet = manager.l2WalletToL1Wallet(msg.sender); + require(l1Wallet != address(0), "NOT_L1_WALLET"); + require(_amount <= graphToken.balanceOf(msg.sender), "INSUFFICIENT_BALANCE"); + require(_amount != 0, "ZERO_AMOUNT"); + + graphToken.transferFrom(msg.sender, address(this), _amount); + graphToken.approve(address(l2Gateway), _amount); + + // Send the tokens through the L2GraphTokenGateway to the L1 wallet counterpart + l2Gateway.outboundTransfer(l1GraphToken, l1Wallet, _amount, 0, 0, ""); + emit LockedFundsSentToL1(l1Wallet, msg.sender, address(manager), _amount); + } +} diff --git a/packages/token-distribution/contracts/L2GraphTokenLockWallet.sol b/packages/token-distribution/contracts/L2GraphTokenLockWallet.sol new file mode 100644 index 000000000..905bee460 --- /dev/null +++ b/packages/token-distribution/contracts/L2GraphTokenLockWallet.sol @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import { GraphTokenLockWallet } from "./GraphTokenLockWallet.sol"; +import { Ownable as OwnableInitializable } from "./Ownable.sol"; +import { L2GraphTokenLockManager } from "./L2GraphTokenLockManager.sol"; + +/** + * @title L2GraphTokenLockWallet + * @notice This contract is built on top of the base GraphTokenLock functionality. + * It allows wallet beneficiaries to use the deposited funds to perform specific function calls + * on specific contracts. + * + * The idea is that supporters with locked tokens can participate in the protocol + * but disallow any release before the vesting/lock schedule. + * The beneficiary can issue authorized function calls to this contract that will + * get forwarded to a target contract. A target contract is any of our protocol contracts. + * The function calls allowed are queried to the GraphTokenLockManager, this way + * the same configuration can be shared for all the created lock wallet contracts. + * + * This L2 variant includes a special initializer so that it can be created from + * a wallet's data received from L1. These transferred wallets will not allow releasing + * funds in L2 until the end of the vesting timeline, but they can allow withdrawing + * funds back to L1 using the L2GraphTokenLockTransferTool contract. + * + * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1, + * so releasing surplus tokens might also only be possible by bridging tokens back to L1. + * + * NOTE: Contracts used as target must have its function signatures checked to avoid collisions + * with any of this contract functions. + * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience + * the maximum amount of tokens is authorized. + * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT. + */ +contract L2GraphTokenLockWallet is GraphTokenLockWallet { + // Initializer when created from a message from L1 + function initializeFromL1( + address _manager, + address _token, + L2GraphTokenLockManager.TransferredWalletData calldata _walletData + ) external { + require(!isInitialized, "Already initialized"); + isInitialized = true; + + OwnableInitializable._initialize(_walletData.owner); + beneficiary = _walletData.beneficiary; + token = IERC20(_token); + + managedAmount = _walletData.managedAmount; + + startTime = _walletData.startTime; + endTime = _walletData.endTime; + periods = 1; + isAccepted = true; + + // Optionals + releaseStartTime = _walletData.endTime; + revocable = Revocability.Disabled; + + _setManager(_manager); + } +} diff --git a/packages/token-distribution/contracts/MathUtils.sol b/packages/token-distribution/contracts/MathUtils.sol new file mode 100644 index 000000000..742c52c37 --- /dev/null +++ b/packages/token-distribution/contracts/MathUtils.sol @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +library MathUtils { + function min(uint256 a, uint256 b) internal pure returns (uint256) { + return a < b ? a : b; + } +} diff --git a/packages/token-distribution/contracts/MinimalProxyFactory.sol b/packages/token-distribution/contracts/MinimalProxyFactory.sol new file mode 100644 index 000000000..ca1f03ee1 --- /dev/null +++ b/packages/token-distribution/contracts/MinimalProxyFactory.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; +import { Create2 } from "@openzeppelin/contracts/utils/Create2.sol"; + +/** + * @title MinimalProxyFactory: a factory contract for creating minimal proxies + * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol + * Based on https://eips.ethereum.org/EIPS/eip-1167 + */ +contract MinimalProxyFactory { + /// @dev Emitted when a new proxy is created + event ProxyCreated(address indexed proxy); + + /** + * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation + * @dev Uses address(this) as deployer to compute the address. Only for backwards compatibility. + * @param _salt Bytes32 salt to use for CREATE2 + * @param _implementation Address of the proxy target implementation + * @return Address of the counterfactual MinimalProxy + */ + function getDeploymentAddress(bytes32 _salt, address _implementation) public view returns (address) { + return getDeploymentAddress(_salt, _implementation, address(this)); + } + + /** + * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation + * @param _salt Bytes32 salt to use for CREATE2 + * @param _implementation Address of the proxy target implementation + * @param _deployer Address of the deployer that creates the contract + * @return Address of the counterfactual MinimalProxy + */ + function getDeploymentAddress( + bytes32 _salt, + address _implementation, + address _deployer + ) public pure returns (address) { + return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer); + } + + /** + * @dev Deploys a MinimalProxy with CREATE2 + * @param _salt Bytes32 salt to use for CREATE2 + * @param _implementation Address of the proxy target implementation + * @param _data Bytes with the initializer call + * @return Address of the deployed MinimalProxy + */ + function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) { + address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation)); + + emit ProxyCreated(proxyAddress); + + // Call function with data + if (_data.length > 0) { + Address.functionCall(proxyAddress, _data); + } + + return proxyAddress; + } + + /** + * @dev Gets the MinimalProxy bytecode + * @param _implementation Address of the proxy target implementation + * @return MinimalProxy bytecode + */ + function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) { + bytes10 creation = 0x3d602d80600a3d3981f3; + bytes10 prefix = 0x363d3d373d3d3d363d73; + bytes20 targetBytes = bytes20(_implementation); + bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3; + return abi.encodePacked(creation, prefix, targetBytes, suffix); + } +} diff --git a/packages/token-distribution/contracts/Ownable.sol b/packages/token-distribution/contracts/Ownable.sol new file mode 100644 index 000000000..73ec22821 --- /dev/null +++ b/packages/token-distribution/contracts/Ownable.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +/** + * @dev Contract module which provides a basic access control mechanism, where + * there is an account (an owner) that can be granted exclusive access to + * specific functions. + * + * The owner account will be passed on initialization of the contract. This + * can later be changed with {transferOwnership}. + * + * This module is used through inheritance. It will make available the modifier + * `onlyOwner`, which can be applied to your functions to restrict their use to + * the owner. + */ +contract Ownable { + /// @dev Owner of the contract, can be retrieved with the public owner() function + address private _owner; + /// @dev Since upgradeable contracts might inherit this, we add a storage gap + /// to allow adding variables here without breaking the proxy storage layout + uint256[50] private __gap; + + /// @dev Emitted when ownership of the contract is transferred + event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); + + /** + * @dev Initializes the contract setting the deployer as the initial owner. + */ + function _initialize(address owner) internal { + _owner = owner; + emit OwnershipTransferred(address(0), owner); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return _owner; + } + + /** + * @dev Throws if called by any account other than the owner. + */ + modifier onlyOwner() { + require(_owner == msg.sender, "Ownable: caller is not the owner"); + _; + } + + /** + * @dev Leaves the contract without owner. It will not be possible to call + * `onlyOwner` functions anymore. Can only be called by the current owner. + * + * NOTE: Renouncing ownership will leave the contract without an owner, + * thereby removing any functionality that is only available to the owner. + */ + function renounceOwnership() external virtual onlyOwner { + emit OwnershipTransferred(_owner, address(0)); + _owner = address(0); + } + + /** + * @dev Transfers ownership of the contract to a new account (`newOwner`). + * Can only be called by the current owner. + */ + function transferOwnership(address newOwner) external virtual onlyOwner { + require(newOwner != address(0), "Ownable: new owner is the zero address"); + emit OwnershipTransferred(_owner, newOwner); + _owner = newOwner; + } +} diff --git a/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol b/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol new file mode 100644 index 000000000..bf2968309 --- /dev/null +++ b/packages/token-distribution/contracts/arbitrum/ITokenGateway.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2020, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Originally copied from: + * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals + * + * MODIFIED from Offchain Labs' implementation: + * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com) + * + */ + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +interface ITokenGateway { + /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated + // event OutboundTransferInitiated( + // address token, + // address indexed _from, + // address indexed _to, + // uint256 indexed _transferId, + // uint256 _amount, + // bytes _data + // ); + + /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized + // event InboundTransferFinalized( + // address token, + // address indexed _from, + // address indexed _to, + // uint256 indexed _transferId, + // uint256 _amount, + // bytes _data + // ); + + function outboundTransfer( + address _token, + address _to, + uint256 _amount, + uint256 _maxGas, + uint256 _gasPriceBid, + bytes calldata _data + ) external payable returns (bytes memory); + + function finalizeInboundTransfer( + address _token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external payable; + + /** + * @notice Calculate the address used when bridging an ERC20 token + * @dev the L1 and L2 address oracles may not always be in sync. + * For example, a custom token may have been registered but not deployed or the contract self destructed. + * @param l1ERC20 address of L1 token + * @return L2 address of a bridged ERC20 token + */ + function calculateL2TokenAddress(address l1ERC20) external view returns (address); +} diff --git a/packages/token-distribution/contracts/tests/BridgeMock.sol b/packages/token-distribution/contracts/tests/BridgeMock.sol new file mode 100644 index 000000000..643a20428 --- /dev/null +++ b/packages/token-distribution/contracts/tests/BridgeMock.sol @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity ^0.7.3; + +import "./arbitrum/IBridge.sol"; + +/** + * @title Arbitrum Bridge mock contract + * @dev This contract implements Arbitrum's IBridge interface for testing purposes + */ +contract BridgeMock is IBridge { + /// Address of the (mock) Arbitrum Inbox + address public inbox; + /// Address of the (mock) Arbitrum Outbox + address public outbox; + /// Index of the next message on the inbox messages array + uint256 public messageIndex; + /// Inbox messages array + bytes32[] public override inboxAccs; + + /** + * @notice Deliver a message to the inbox. The encoded message will be + * added to the inbox array, and messageIndex will be incremented. + * @param _kind Type of the message + * @param _sender Address that is sending the message + * @param _messageDataHash keccak256 hash of the message data + * @return The next index for the inbox array + */ + function deliverMessageToInbox( + uint8 _kind, + address _sender, + bytes32 _messageDataHash + ) external payable override returns (uint256) { + messageIndex = messageIndex + 1; + inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash))); + emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash); + return messageIndex; + } + + /** + * @notice Executes an L1 function call incoing from L2. This can only be called + * by the Outbox. + * @param _destAddr Contract to call + * @param _amount ETH value to send + * @param _data Calldata for the function call + * @return True if the call was successful, false otherwise + * @return Return data from the call + */ + function executeCall( + address _destAddr, + uint256 _amount, + bytes calldata _data + ) external override returns (bool, bytes memory) { + require(outbox == msg.sender, "NOT_FROM_OUTBOX"); + bool success; + bytes memory returnData; + + // solhint-disable-next-line avoid-low-level-calls + (success, returnData) = _destAddr.call{ value: _amount }(_data); + emit BridgeCallTriggered(msg.sender, _destAddr, _amount, _data); + return (success, returnData); + } + + /** + * @notice Set the address of the inbox. Anyone can call this, because it's a mock. + * @param _inbox Address of the inbox + * @param _enabled Enable the inbox (ignored) + */ + function setInbox(address _inbox, bool _enabled) external override { + inbox = _inbox; + emit InboxToggle(inbox, _enabled); + } + + /** + * @notice Set the address of the outbox. Anyone can call this, because it's a mock. + * @param _outbox Address of the outbox + * @param _enabled Enable the outbox (ignored) + */ + function setOutbox(address _outbox, bool _enabled) external override { + outbox = _outbox; + emit OutboxToggle(outbox, _enabled); + } + + // View functions + + /** + * @notice Getter for the active outbox (in this case there's only one) + */ + function activeOutbox() external view override returns (address) { + return outbox; + } + + /** + * @notice Getter for whether an address is an allowed inbox (in this case there's only one) + * @param _inbox Address to check + * @return True if the address is the allowed inbox, false otherwise + */ + function allowedInboxes(address _inbox) external view override returns (bool) { + return _inbox == inbox; + } + + /** + * @notice Getter for whether an address is an allowed outbox (in this case there's only one) + * @param _outbox Address to check + * @return True if the address is the allowed outbox, false otherwise + */ + function allowedOutboxes(address _outbox) external view override returns (bool) { + return _outbox == outbox; + } + + /** + * @notice Getter for the count of messages in the inboxAccs + * @return Number of messages in inboxAccs + */ + function messageCount() external view override returns (uint256) { + return inboxAccs.length; + } +} diff --git a/packages/token-distribution/contracts/tests/GraphTokenMock.sol b/packages/token-distribution/contracts/tests/GraphTokenMock.sol new file mode 100644 index 000000000..bc52b9456 --- /dev/null +++ b/packages/token-distribution/contracts/tests/GraphTokenMock.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title Graph Token Mock contract. + * @dev Used for testing purposes, DO NOT USE IN PRODUCTION + */ +contract GraphTokenMock is Ownable, ERC20 { + /** + * @notice Contract Constructor. + * @param _initialSupply Initial supply + * @param _mintTo Address to whitch to mint the initial supply + */ + constructor(uint256 _initialSupply, address _mintTo) ERC20("Graph Token Mock", "GRT-Mock") { + // Deploy to mint address + _mint(_mintTo, _initialSupply); + } + + /** + * @notice Mint tokens to an address from the bridge. + * (The real one has an onlyGateway modifier) + * @param _to Address to mint tokens to + * @param _amount Amount of tokens to mint + */ + function bridgeMint(address _to, uint256 _amount) external { + _mint(_to, _amount); + } + + /** + * @notice Burn tokens from an address from the bridge. + * (The real one has an onlyGateway modifier) + * @param _from Address to burn tokens from + * @param _amount Amount of tokens to burn + */ + function bridgeBurn(address _from, uint256 _amount) external { + _burn(_from, _amount); + } +} diff --git a/packages/token-distribution/contracts/tests/InboxMock.sol b/packages/token-distribution/contracts/tests/InboxMock.sol new file mode 100644 index 000000000..7f0fdfb6b --- /dev/null +++ b/packages/token-distribution/contracts/tests/InboxMock.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity ^0.7.3; + +import "./arbitrum/IInbox.sol"; +import "./arbitrum/AddressAliasHelper.sol"; + +/** + * @title Arbitrum Inbox mock contract + * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes + */ +contract InboxMock is IInbox { + /// @dev Type indicator for a standard L2 message + uint8 internal constant L2_MSG = 3; + /// @dev Type indicator for a retryable ticket message + // solhint-disable-next-line const-name-snakecase + uint8 internal constant L1MessageType_submitRetryableTx = 9; + /// Address of the Bridge (mock) contract + IBridge public override bridge; + + /** + * @notice Send a message to L2 (by delivering it to the Bridge) + * @param _messageData Encoded data to send in the message + * @return Message number returned by the inbox + */ + function sendL2Message(bytes calldata _messageData) external override returns (uint256) { + uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData)); + emit InboxMessageDelivered(msgNum, _messageData); + return msgNum; + } + + /** + * @notice Set the address of the (mock) bridge + * @param _bridge Address of the bridge + */ + function setBridge(address _bridge) external { + bridge = IBridge(_bridge); + } + + /** + * @notice Unimplemented in this mock + */ + function sendUnsignedTransaction( + uint256, + uint256, + uint256, + address, + uint256, + bytes calldata + ) external pure override returns (uint256) { + revert("Unimplemented"); + } + + /** + * @notice Unimplemented in this mock + */ + function sendContractTransaction( + uint256, + uint256, + address, + uint256, + bytes calldata + ) external pure override returns (uint256) { + revert("Unimplemented"); + } + + /** + * @notice Unimplemented in this mock + */ + function sendL1FundedUnsignedTransaction( + uint256, + uint256, + uint256, + address, + bytes calldata + ) external payable override returns (uint256) { + revert("Unimplemented"); + } + + /** + * @notice Unimplemented in this mock + */ + function sendL1FundedContractTransaction( + uint256, + uint256, + address, + bytes calldata + ) external payable override returns (uint256) { + revert("Unimplemented"); + } + + /** + * @notice Creates a retryable ticket for an L2 transaction + * @param _destAddr Address of the contract to call in L2 + * @param _arbTxCallValue Callvalue to use in the L2 transaction + * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei + * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost + * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled + * @param _maxGas Max gas for the L2 transcation + * @param _gasPriceBid Gas price bid on L2 + * @param _data Encoded calldata for the L2 transaction (including function selector) + * @return Message number returned by the bridge + */ + function createRetryableTicket( + address _destAddr, + uint256 _arbTxCallValue, + uint256 _maxSubmissionCost, + address _submissionRefundAddress, + address _valueRefundAddress, + uint256 _maxGas, + uint256 _gasPriceBid, + bytes calldata _data + ) external payable override returns (uint256) { + _submissionRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_submissionRefundAddress); + _valueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_valueRefundAddress); + return + _deliverMessage( + L1MessageType_submitRetryableTx, + msg.sender, + abi.encodePacked( + uint256(uint160(bytes20(_destAddr))), + _arbTxCallValue, + msg.value, + _maxSubmissionCost, + uint256(uint160(bytes20(_submissionRefundAddress))), + uint256(uint160(bytes20(_valueRefundAddress))), + _maxGas, + _gasPriceBid, + _data.length, + _data + ) + ); + } + + /** + * @notice Unimplemented in this mock + */ + function depositEth(uint256) external payable override returns (uint256) { + revert("Unimplemented"); + } + + /** + * @notice Unimplemented in this mock + */ + function pauseCreateRetryables() external pure override { + revert("Unimplemented"); + } + + /** + * @notice Unimplemented in this mock + */ + function unpauseCreateRetryables() external pure override { + revert("Unimplemented"); + } + + /** + * @notice Unimplemented in this mock + */ + function startRewriteAddress() external pure override { + revert("Unimplemented"); + } + + /** + * @notice Unimplemented in this mock + */ + function stopRewriteAddress() external pure override { + revert("Unimplemented"); + } + + /** + * @dev Deliver a message to the bridge + * @param _kind Type of the message + * @param _sender Address that is sending the message + * @param _messageData Encoded message data + * @return Message number returned by the bridge + */ + function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) { + uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData)); + emit InboxMessageDelivered(msgNum, _messageData); + return msgNum; + } + + /** + * @dev Deliver a message to the bridge + * @param _kind Type of the message + * @param _sender Address that is sending the message + * @param _messageDataHash keccak256 hash of the encoded message data + * @return Message number returned by the bridge + */ + function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) { + return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash); + } +} diff --git a/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol b/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol new file mode 100644 index 000000000..af0d6e34d --- /dev/null +++ b/packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol @@ -0,0 +1,168 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol"; +import { ITokenGateway } from "../arbitrum//ITokenGateway.sol"; + +/** + * @title L1 Token Gateway mock contract + * @dev Used for testing purposes, DO NOT USE IN PRODUCTION + */ +contract L1TokenGatewayMock is Ownable { + using SafeMath for uint256; + /// Next sequence number to return when outboundTransfer is called + uint256 public nextSeqNum; + + /// @dev Emitted when a (fake) retryable ticket is created + event FakeTxToL2( + address from, + uint256 value, + uint256 maxGas, + uint256 gasPriceBid, + uint256 maxSubmissionCost, + bytes outboundCalldata + ); + + /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2 + event DepositInitiated( + address l1Token, + address indexed from, + address indexed to, + uint256 indexed sequenceNumber, + uint256 amount + ); + + /** + * @notice L1 Token Gateway Contract Constructor. + */ + constructor() {} + + /** + * @notice Creates and sends a fake retryable ticket to transfer GRT to L2. + * This mock will actually just emit an event with parameters equivalent to what the real L1GraphTokenGateway + * would send to L2. + * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router) + * @param _to Recipient address on L2 + * @param _amount Amount of tokens to tranfer + * @param _maxGas Gas limit for L2 execution of the ticket + * @param _gasPriceBid Price per gas on L2 + * @param _data Encoded maxSubmissionCost and sender address along with additional calldata + * @return Sequence number of the retryable ticket created by Inbox (always ) + */ + function outboundTransfer( + address _l1Token, + address _to, + uint256 _amount, + uint256 _maxGas, + uint256 _gasPriceBid, + bytes calldata _data + ) external payable returns (bytes memory) { + require(_amount > 0, "INVALID_ZERO_AMOUNT"); + require(_to != address(0), "INVALID_DESTINATION"); + + // nested scopes to avoid stack too deep errors + address from; + uint256 seqNum = nextSeqNum; + nextSeqNum += 1; + { + uint256 maxSubmissionCost; + bytes memory outboundCalldata; + { + bytes memory extraData; + (from, maxSubmissionCost, extraData) = _parseOutboundData(_data); + require(maxSubmissionCost > 0, "NO_SUBMISSION_COST"); + + { + // makes sure only sufficient ETH is supplied as required for successful redemption on L2 + // if a user does not desire immediate redemption they should provide + // a msg.value of AT LEAST maxSubmissionCost + uint256 expectedEth = maxSubmissionCost.add(_maxGas.mul(_gasPriceBid)); + require(msg.value >= expectedEth, "WRONG_ETH_VALUE"); + } + outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData); + } + { + // transfer tokens to escrow + IERC20(_l1Token).transferFrom(from, address(this), _amount); + + emit FakeTxToL2(from, msg.value, _maxGas, _gasPriceBid, maxSubmissionCost, outboundCalldata); + } + } + emit DepositInitiated(_l1Token, from, _to, seqNum, _amount); + + return abi.encode(seqNum); + } + + /** + * @notice (Mock) Receives withdrawn tokens from L2 + * Actually does nothing, just keeping it here as its useful to define the expected + * calldata for the outgoing transfer in tests. + * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router) + * @param _from Address of the sender + * @param _to Recepient address on L1 + * @param _amount Amount of tokens transferred + * @param _data Additional calldata + */ + function finalizeInboundTransfer( + address _l1Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external payable {} + + /** + * @notice Creates calldata required to create a retryable ticket + * @dev encodes the target function with its params which + * will be called on L2 when the retryable ticket is redeemed + * @param _l1Token Address of the Graph token contract on L1 + * @param _from Address on L1 from which we're transferring tokens + * @param _to Address on L2 to which we're transferring tokens + * @param _amount Amount of GRT to transfer + * @param _data Additional call data for the L2 transaction, which must be empty unless the caller is whitelisted + * @return Encoded calldata (including function selector) for the L2 transaction + */ + function getOutboundCalldata( + address _l1Token, + address _from, + address _to, + uint256 _amount, + bytes memory _data + ) public pure returns (bytes memory) { + bytes memory emptyBytes; + + return + abi.encodeWithSelector( + ITokenGateway.finalizeInboundTransfer.selector, + _l1Token, + _from, + _to, + _amount, + abi.encode(emptyBytes, _data) + ); + } + + /** + * @notice Decodes calldata required for transfer of tokens to L2 + * @dev Data must include maxSubmissionCost, extraData can be left empty. When the router + * sends an outbound message, data also contains the from address, but this mock + * doesn't consider this case + * @param _data Encoded callhook data containing maxSubmissionCost and extraData + * @return Sender of the tx + * @return Max ether value used to submit the retryable ticket + * @return Additional data sent to L2 + */ + function _parseOutboundData(bytes memory _data) private view returns (address, uint256, bytes memory) { + address from; + uint256 maxSubmissionCost; + bytes memory extraData; + from = msg.sender; + // User-encoded data contains the max retryable ticket submission cost + // and additional L2 calldata + (maxSubmissionCost, extraData) = abi.decode(_data, (uint256, bytes)); + return (from, maxSubmissionCost, extraData); + } +} diff --git a/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol b/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol new file mode 100644 index 000000000..72665b8d4 --- /dev/null +++ b/packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { ITokenGateway } from "../arbitrum//ITokenGateway.sol"; +import { GraphTokenMock } from "./GraphTokenMock.sol"; +import { ICallhookReceiver } from "../ICallhookReceiver.sol"; + +/** + * @title L2 Token Gateway mock contract + * @dev Used for testing purposes, DO NOT USE IN PRODUCTION + */ +contract L2TokenGatewayMock is Ownable { + /// Address of the L1 GRT contract + address public immutable l1Token; + /// Address of the L2 GRT contract + address public immutable l2Token; + /// Next ID to return when sending an outboundTransfer + uint256 public nextId; + + /// @dev Emitted when a (fake) transaction to L1 is created + event FakeTxToL1(address from, bytes outboundCalldata); + /// @dev Emitted when a (fake) retryable ticket is received from L1 + event DepositFinalized(address token, address indexed from, address indexed to, uint256 amount); + + /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are withdrawn to L1 from L2 + event WithdrawalInitiated( + address l1Token, + address indexed from, + address indexed to, + uint256 indexed sequenceNumber, + uint256 amount + ); + + /** + * @notice L2 Token Gateway Contract Constructor. + * @param _l1Token Address of the L1 GRT contract + * @param _l2Token Address of the L2 GRT contract + */ + constructor(address _l1Token, address _l2Token) { + l1Token = _l1Token; + l2Token = _l2Token; + } + + /** + * @notice Creates and sends a (fake) transfer of GRT to L1. + * This mock will actually just emit an event with parameters equivalent to what the real L2GraphTokenGateway + * would send to L1. + * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router) + * @param _to Recipient address on L2 + * @param _amount Amount of tokens to tranfer + * @param _data Encoded maxSubmissionCost and sender address along with additional calldata + * @return ID of the L2-L1 message (incrementing on every call) + */ + function outboundTransfer( + address _l1Token, + address _to, + uint256 _amount, + uint256, + uint256, + bytes calldata _data + ) external payable returns (bytes memory) { + require(_l1Token == l1Token, "INVALID_L1_TOKEN"); + require(_amount > 0, "INVALID_ZERO_AMOUNT"); + require(_to != address(0), "INVALID_DESTINATION"); + + // nested scopes to avoid stack too deep errors + address from; + uint256 id = nextId; + nextId += 1; + { + bytes memory outboundCalldata; + { + bytes memory extraData; + (from, extraData) = _parseOutboundData(_data); + + require(msg.value == 0, "!value"); + require(extraData.length == 0, "!extraData"); + outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData); + } + { + // burn tokens from the sender, they will be released from escrow in L1 + GraphTokenMock(l2Token).bridgeBurn(from, _amount); + + emit FakeTxToL1(from, outboundCalldata); + } + } + emit WithdrawalInitiated(_l1Token, from, _to, id, _amount); + + return abi.encode(id); + } + + /** + * @notice (Mock) Receives withdrawn tokens from L1 + * Implements calling callhooks if data is non-empty. + * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router) + * @param _from Address of the sender + * @param _to Recipient address on L1 + * @param _amount Amount of tokens transferred + * @param _data Additional calldata, will trigger an onTokenTransfer call if non-empty + */ + function finalizeInboundTransfer( + address _l1Token, + address _from, + address _to, + uint256 _amount, + bytes calldata _data + ) external payable { + require(_l1Token == l1Token, "TOKEN_NOT_GRT"); + require(msg.value == 0, "INVALID_NONZERO_VALUE"); + + GraphTokenMock(l2Token).bridgeMint(_to, _amount); + + if (_data.length > 0) { + ICallhookReceiver(_to).onTokenTransfer(_from, _amount, _data); + } + + emit DepositFinalized(_l1Token, _from, _to, _amount); + } + + /** + * @notice Calculate the L2 address of a bridged token + * @dev In our case, this would only work for GRT. + * @param l1ERC20 address of L1 GRT contract + * @return L2 address of the bridged GRT token + */ + function calculateL2TokenAddress(address l1ERC20) public view returns (address) { + if (l1ERC20 != l1Token) { + return address(0); + } + return l2Token; + } + + /** + * @notice Creates calldata required to create a tx to L1 + * @param _l1Token Address of the Graph token contract on L1 + * @param _from Address on L2 from which we're transferring tokens + * @param _to Address on L1 to which we're transferring tokens + * @param _amount Amount of GRT to transfer + * @param _data Additional call data for the L1 transaction, which must be empty + * @return Encoded calldata (including function selector) for the L1 transaction + */ + function getOutboundCalldata( + address _l1Token, + address _from, + address _to, + uint256 _amount, + bytes memory _data + ) public pure returns (bytes memory) { + return + abi.encodeWithSelector( + ITokenGateway.finalizeInboundTransfer.selector, + _l1Token, + _from, + _to, + _amount, + abi.encode(0, _data) + ); + } + + /** + * @dev Decodes calldata required for transfer of tokens to L1. + * extraData can be left empty + * @param _data Encoded callhook data + * @return Sender of the tx + * @return Any other data sent to L1 + */ + function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) { + address from; + bytes memory extraData; + // The mock doesn't take messages from the Router + from = msg.sender; + extraData = _data; + return (from, extraData); + } +} diff --git a/packages/token-distribution/contracts/tests/Stakes.sol b/packages/token-distribution/contracts/tests/Stakes.sol new file mode 100644 index 000000000..bf140aa8f --- /dev/null +++ b/packages/token-distribution/contracts/tests/Stakes.sol @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/math/SafeMath.sol"; + +/** + * @title A collection of data structures and functions to manage the Indexer Stake state. + * Used for low-level state changes, require() conditions should be evaluated + * at the caller function scope. + */ +library Stakes { + using SafeMath for uint256; + using Stakes for Stakes.Indexer; + + struct Indexer { + uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer) + uint256 tokensAllocated; // Tokens used in allocations + uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period + uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn + } + + /** + * @dev Deposit tokens to the indexer stake. + * @param stake Stake data + * @param _tokens Amount of tokens to deposit + */ + function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal { + stake.tokensStaked = stake.tokensStaked.add(_tokens); + } + + /** + * @dev Release tokens from the indexer stake. + * @param stake Stake data + * @param _tokens Amount of tokens to release + */ + function release(Stakes.Indexer storage stake, uint256 _tokens) internal { + stake.tokensStaked = stake.tokensStaked.sub(_tokens); + } + + /** + * @dev Allocate tokens from the main stack to a SubgraphDeployment. + * @param stake Stake data + * @param _tokens Amount of tokens to allocate + */ + function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal { + stake.tokensAllocated = stake.tokensAllocated.add(_tokens); + } + + /** + * @dev Unallocate tokens from a SubgraphDeployment back to the main stack. + * @param stake Stake data + * @param _tokens Amount of tokens to unallocate + */ + function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal { + stake.tokensAllocated = stake.tokensAllocated.sub(_tokens); + } + + /** + * @dev Lock tokens until a thawing period pass. + * @param stake Stake data + * @param _tokens Amount of tokens to unstake + * @param _period Period in blocks that need to pass before withdrawal + */ + function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal { + // Take into account period averaging for multiple unstake requests + uint256 lockingPeriod = _period; + if (stake.tokensLocked > 0) { + lockingPeriod = stake.getLockingPeriod(_tokens, _period); + } + + // Update balances + stake.tokensLocked = stake.tokensLocked.add(_tokens); + stake.tokensLockedUntil = block.number.add(lockingPeriod); + } + + /** + * @dev Unlock tokens. + * @param stake Stake data + * @param _tokens Amount of tokens to unkock + */ + function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal { + stake.tokensLocked = stake.tokensLocked.sub(_tokens); + if (stake.tokensLocked == 0) { + stake.tokensLockedUntil = 0; + } + } + + /** + * @dev Take all tokens out from the locked stake for withdrawal. + * @param stake Stake data + * @return Amount of tokens being withdrawn + */ + function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) { + // Calculate tokens that can be released + uint256 tokensToWithdraw = stake.tokensWithdrawable(); + + if (tokensToWithdraw > 0) { + // Reset locked tokens + stake.unlockTokens(tokensToWithdraw); + + // Decrease indexer stake + stake.release(tokensToWithdraw); + } + + return tokensToWithdraw; + } + + /** + * @dev Get the locking period of the tokens to unstake. + * If already unstaked before calculate the weighted average. + * @param stake Stake data + * @param _tokens Amount of tokens to unstake + * @param _thawingPeriod Period in blocks that need to pass before withdrawal + * @return True if staked + */ + function getLockingPeriod( + Stakes.Indexer memory stake, + uint256 _tokens, + uint256 _thawingPeriod + ) internal view returns (uint256) { + uint256 blockNum = block.number; + uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0; + uint256 periodB = _thawingPeriod; + uint256 stakeA = stake.tokensLocked; + uint256 stakeB = _tokens; + return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB)); + } + + /** + * @dev Return true if there are tokens staked by the Indexer. + * @param stake Stake data + * @return True if staked + */ + function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) { + return stake.tokensStaked > 0; + } + + /** + * @dev Return the amount of tokens used in allocations and locked for withdrawal. + * @param stake Stake data + * @return Token amount + */ + function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) { + return stake.tokensAllocated.add(stake.tokensLocked); + } + + /** + * @dev Return the amount of tokens staked not considering the ones that are already going + * through the thawing period or are ready for withdrawal. We call it secure stake because + * it is not subject to change by a withdraw call from the indexer. + * @param stake Stake data + * @return Token amount + */ + function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) { + return stake.tokensStaked.sub(stake.tokensLocked); + } + + /** + * @dev Tokens free balance on the indexer stake that can be used for any purpose. + * Any token that is allocated cannot be used as well as tokens that are going through the + * thawing period or are withdrawable + * Calc: tokensStaked - tokensAllocated - tokensLocked + * @param stake Stake data + * @return Token amount + */ + function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) { + return stake.tokensAvailableWithDelegation(0); + } + + /** + * @dev Tokens free balance on the indexer stake that can be used for allocations. + * This function accepts a parameter for extra delegated capacity that takes into + * account delegated tokens + * @param stake Stake data + * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability + * @return Token amount + */ + function tokensAvailableWithDelegation( + Stakes.Indexer memory stake, + uint256 _delegatedCapacity + ) internal pure returns (uint256) { + uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity); + uint256 _tokensUsed = stake.tokensUsed(); + // If more tokens are used than the current capacity, the indexer is overallocated. + // This means the indexer doesn't have available capacity to create new allocations. + // We can reach this state when the indexer has funds allocated and then any + // of these conditions happen: + // - The delegationCapacity ratio is reduced. + // - The indexer stake is slashed. + // - A delegator removes enough stake. + if (_tokensUsed > tokensCapacity) { + // Indexer stake is over allocated: return 0 to avoid stake to be used until + // the overallocation is restored by staking more tokens, unallocating tokens + // or using more delegated funds + return 0; + } + return tokensCapacity.sub(_tokensUsed); + } + + /** + * @dev Tokens available for withdrawal after thawing period. + * @param stake Stake data + * @return Token amount + */ + function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) { + // No tokens to withdraw before locking period + if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) { + return 0; + } + return stake.tokensLocked; + } +} diff --git a/packages/token-distribution/contracts/tests/StakingMock.sol b/packages/token-distribution/contracts/tests/StakingMock.sol new file mode 100644 index 000000000..8c5fffc80 --- /dev/null +++ b/packages/token-distribution/contracts/tests/StakingMock.sol @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +import "./Stakes.sol"; + +contract StakingMock { + using SafeMath for uint256; + using Stakes for Stakes.Indexer; + + // -- State -- + + uint256 public minimumIndexerStake = 100e18; + uint256 public thawingPeriod = 10; // 10 blocks + IERC20 public token; + + // Indexer stakes : indexer => Stake + mapping(address => Stakes.Indexer) public stakes; + + /** + * @dev Emitted when `indexer` stake `tokens` amount. + */ + event StakeDeposited(address indexed indexer, uint256 tokens); + + /** + * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block. + */ + event StakeLocked(address indexed indexer, uint256 tokens, uint256 until); + + /** + * @dev Emitted when `indexer` withdrew `tokens` staked. + */ + event StakeWithdrawn(address indexed indexer, uint256 tokens); + + // Contract constructor. + constructor(IERC20 _token) { + require(address(_token) != address(0), "!token"); + token = _token; + } + + receive() external payable {} + + /** + * @dev Deposit tokens on the indexer stake. + * @param _tokens Amount of tokens to stake + */ + function stake(uint256 _tokens) external { + stakeTo(msg.sender, _tokens); + } + + /** + * @dev Deposit tokens on the indexer stake. + * @param _indexer Address of the indexer + * @param _tokens Amount of tokens to stake + */ + function stakeTo(address _indexer, uint256 _tokens) public { + require(_tokens > 0, "!tokens"); + + // Ensure minimum stake + require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, "!minimumIndexerStake"); + + // Transfer tokens to stake from caller to this contract + require(token.transferFrom(msg.sender, address(this), _tokens), "!transfer"); + + // Stake the transferred tokens + _stake(_indexer, _tokens); + } + + /** + * @dev Unstake tokens from the indexer stake, lock them until thawing period expires. + * @param _tokens Amount of tokens to unstake + */ + function unstake(uint256 _tokens) external { + address indexer = msg.sender; + Stakes.Indexer storage indexerStake = stakes[indexer]; + + require(_tokens > 0, "!tokens"); + require(indexerStake.hasTokens(), "!stake"); + require(indexerStake.tokensAvailable() >= _tokens, "!stake-avail"); + + // Ensure minimum stake + uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens); + require(newStake == 0 || newStake >= minimumIndexerStake, "!minimumIndexerStake"); + + // Before locking more tokens, withdraw any unlocked ones + uint256 tokensToWithdraw = indexerStake.tokensWithdrawable(); + if (tokensToWithdraw > 0) { + _withdraw(indexer); + } + + indexerStake.lockTokens(_tokens, thawingPeriod); + + emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil); + } + + /** + * @dev Withdraw indexer tokens once the thawing period has passed. + */ + function withdraw() external { + _withdraw(msg.sender); + } + + function _stake(address _indexer, uint256 _tokens) internal { + // Deposit tokens into the indexer stake + Stakes.Indexer storage indexerStake = stakes[_indexer]; + indexerStake.deposit(_tokens); + + emit StakeDeposited(_indexer, _tokens); + } + + /** + * @dev Withdraw indexer tokens once the thawing period has passed. + * @param _indexer Address of indexer to withdraw funds from + */ + function _withdraw(address _indexer) private { + // Get tokens available for withdraw and update balance + uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens(); + require(tokensToWithdraw > 0, "!tokens"); + + // Return tokens to the indexer + require(token.transfer(_indexer, tokensToWithdraw), "!transfer"); + + emit StakeWithdrawn(_indexer, tokensToWithdraw); + } +} diff --git a/packages/token-distribution/contracts/tests/WalletMock.sol b/packages/token-distribution/contracts/tests/WalletMock.sol new file mode 100644 index 000000000..872760d6e --- /dev/null +++ b/packages/token-distribution/contracts/tests/WalletMock.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.7.3; +pragma experimental ABIEncoderV2; + +import { Address } from "@openzeppelin/contracts/utils/Address.sol"; + +/** + * @title WalletMock: a mock wallet contract for testing purposes + * @dev For testing only, DO NOT USE IN PRODUCTION. + * This is used to test L1-L2 transfer tools and to create scenarios + * where an invalid wallet calls the transfer tool, e.g. a wallet that has an invalid + * manager, or a wallet that has not been initialized. + */ +contract WalletMock { + /// Target contract for the fallback function (usually a transfer tool contract) + address public immutable target; + /// Address of the GRT (mock) token + address public immutable token; + /// Address of the wallet's manager + address public immutable manager; + /// Whether the wallet has been initialized + bool public immutable isInitialized; + /// Whether the beneficiary has accepted the lock + bool public immutable isAccepted; + + /** + * @notice WalletMock constructor + * @dev This constructor sets all the state variables so that + * specific test scenarios can be created just by deploying this contract. + * @param _target Target contract for the fallback function + * @param _token Address of the GRT (mock) token + * @param _manager Address of the wallet's manager + * @param _isInitialized Whether the wallet has been initialized + * @param _isAccepted Whether the beneficiary has accepted the lock + */ + constructor(address _target, address _token, address _manager, bool _isInitialized, bool _isAccepted) { + target = _target; + token = _token; + manager = _manager; + isInitialized = _isInitialized; + isAccepted = _isAccepted; + } + + /** + * @notice Fallback function + * @dev This function calls the target contract with the data sent to this contract. + * This is used to test the L1-L2 transfer tool. + */ + fallback() external payable { + // Call function with data + Address.functionCall(target, msg.data); + } + + /** + * @notice Receive function + * @dev This function is added to avoid compiler warnings, but just reverts. + */ + receive() external payable { + revert("Invalid call"); + } +} diff --git a/packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol b/packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol new file mode 100644 index 000000000..146c1c876 --- /dev/null +++ b/packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2019-2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Originally copied from: + * https://github.com/OffchainLabs/arbitrum/tree/84e64dee6ee82adbf8ec34fd4b86c207a61d9007/packages/arb-bridge-eth + * + * MODIFIED from Offchain Labs' implementation: + * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com) + * + */ + +pragma solidity ^0.7.3; + +library AddressAliasHelper { + uint160 constant offset = uint160(0x1111000000000000000000000000000000001111); + + /// @notice Utility function that converts the address in the L1 that submitted a tx to + /// the inbox to the msg.sender viewed in the L2 + /// @param l1Address the address in the L1 that triggered the tx to L2 + /// @return l2Address L2 address as viewed in msg.sender + function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) { + l2Address = address(uint160(l1Address) + offset); + } + + /// @notice Utility function that converts the msg.sender viewed in the L2 to the + /// address in the L1 that submitted a tx to the inbox + /// @param l2Address L2 address as viewed in msg.sender + /// @return l1Address the address in the L1 that triggered the tx to L2 + function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) { + l1Address = address(uint160(l2Address) - offset); + } +} diff --git a/packages/token-distribution/contracts/tests/arbitrum/IBridge.sol b/packages/token-distribution/contracts/tests/arbitrum/IBridge.sol new file mode 100644 index 000000000..fdfa34eed --- /dev/null +++ b/packages/token-distribution/contracts/tests/arbitrum/IBridge.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Originally copied from: + * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth + * + * MODIFIED from Offchain Labs' implementation: + * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com) + * + */ + +pragma solidity ^0.7.3; + +interface IBridge { + event MessageDelivered( + uint256 indexed messageIndex, + bytes32 indexed beforeInboxAcc, + address inbox, + uint8 kind, + address sender, + bytes32 messageDataHash + ); + + event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data); + + event InboxToggle(address indexed inbox, bool enabled); + + event OutboxToggle(address indexed outbox, bool enabled); + + function deliverMessageToInbox( + uint8 kind, + address sender, + bytes32 messageDataHash + ) external payable returns (uint256); + + function executeCall( + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (bool success, bytes memory returnData); + + // These are only callable by the admin + function setInbox(address inbox, bool enabled) external; + + function setOutbox(address inbox, bool enabled) external; + + // View functions + + function activeOutbox() external view returns (address); + + function allowedInboxes(address inbox) external view returns (bool); + + function allowedOutboxes(address outbox) external view returns (bool); + + function inboxAccs(uint256 index) external view returns (bytes32); + + function messageCount() external view returns (uint256); +} diff --git a/packages/token-distribution/contracts/tests/arbitrum/IInbox.sol b/packages/token-distribution/contracts/tests/arbitrum/IInbox.sol new file mode 100644 index 000000000..0a6e78dc3 --- /dev/null +++ b/packages/token-distribution/contracts/tests/arbitrum/IInbox.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Originally copied from: + * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth + * + * MODIFIED from Offchain Labs' implementation: + * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com) + * + */ + +pragma solidity ^0.7.3; + +import "./IBridge.sol"; +import "./IMessageProvider.sol"; + +interface IInbox is IMessageProvider { + function sendL2Message(bytes calldata messageData) external returns (uint256); + + function sendUnsignedTransaction( + uint256 maxGas, + uint256 gasPriceBid, + uint256 nonce, + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (uint256); + + function sendContractTransaction( + uint256 maxGas, + uint256 gasPriceBid, + address destAddr, + uint256 amount, + bytes calldata data + ) external returns (uint256); + + function sendL1FundedUnsignedTransaction( + uint256 maxGas, + uint256 gasPriceBid, + uint256 nonce, + address destAddr, + bytes calldata data + ) external payable returns (uint256); + + function sendL1FundedContractTransaction( + uint256 maxGas, + uint256 gasPriceBid, + address destAddr, + bytes calldata data + ) external payable returns (uint256); + + function createRetryableTicket( + address destAddr, + uint256 arbTxCallValue, + uint256 maxSubmissionCost, + address submissionRefundAddress, + address valueRefundAddress, + uint256 maxGas, + uint256 gasPriceBid, + bytes calldata data + ) external payable returns (uint256); + + function depositEth(uint256 maxSubmissionCost) external payable returns (uint256); + + function bridge() external view returns (IBridge); + + function pauseCreateRetryables() external; + + function unpauseCreateRetryables() external; + + function startRewriteAddress() external; + + function stopRewriteAddress() external; +} diff --git a/packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol b/packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol new file mode 100644 index 000000000..cf8446af2 --- /dev/null +++ b/packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 + +/* + * Copyright 2021, Offchain Labs, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Originally copied from: + * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth + * + * MODIFIED from Offchain Labs' implementation: + * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com) + * + */ + +pragma solidity ^0.7.3; + +interface IMessageProvider { + event InboxMessageDelivered(uint256 indexed messageNum, bytes data); + + event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum); +} diff --git a/packages/token-distribution/deploy/1_test.ts b/packages/token-distribution/deploy/1_test.ts new file mode 100644 index 000000000..92b626012 --- /dev/null +++ b/packages/token-distribution/deploy/1_test.ts @@ -0,0 +1,32 @@ +import { utils } from 'ethers' +import consola from 'consola' + +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction, DeployOptions } from 'hardhat-deploy/types' + +const { parseEther } = utils + +const logger = consola.create({}) + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const deploy = (name: string, options: DeployOptions) => hre.deployments.deploy(name, options) + const { deployer } = await hre.getNamedAccounts() + + // -- Fake Graph Token -- + + logger.info('Deploying GraphTokenMock...') + + await deploy('GraphTokenMock', { + from: deployer, + args: [ + parseEther('10000000000'), // 10B + deployer, + ], + log: true, + }) +} + +func.skip = (hre: HardhatRuntimeEnvironment) => Promise.resolve(hre.network.name === 'mainnet') +func.tags = ['test'] + +export default func diff --git a/packages/token-distribution/deploy/2_l1_manager_wallet.ts b/packages/token-distribution/deploy/2_l1_manager_wallet.ts new file mode 100644 index 000000000..a2bd7ecac --- /dev/null +++ b/packages/token-distribution/deploy/2_l1_manager_wallet.ts @@ -0,0 +1,73 @@ +import consola from 'consola' +import { utils } from 'ethers' + +import '@nomiclabs/hardhat-ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction, DeployOptions } from 'hardhat-deploy/types' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { GraphTokenLockManager } from '../build/typechain/contracts/GraphTokenLockManager' +import { askConfirm, getDeploymentName, promptContractAddress } from './lib/utils' + +const { parseEther, formatEther } = utils + +const logger = consola.create({}) + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const deploy = (name: string, options: DeployOptions) => hre.deployments.deploy(name, options) + const { deployer } = await hre.getNamedAccounts() + + // -- Graph Token -- + + // Get the token address we will use + const tokenAddress = await promptContractAddress('L1 GRT', logger) + if (!tokenAddress) { + logger.warn('No token address provided') + process.exit(1) + } + + // -- Token Lock Manager -- + + // Deploy the master copy of GraphTokenLockWallet + logger.info('Deploying GraphTokenLockWallet master copy...') + const masterCopySaveName = await getDeploymentName('GraphTokenLockWallet') + const masterCopyDeploy = await deploy(masterCopySaveName, { + from: deployer, + log: true, + contract: 'GraphTokenLockWallet', + }) + + // Deploy the Manager that uses the master copy to clone contracts + logger.info('Deploying GraphTokenLockManager...') + const managerSaveName = await getDeploymentName('GraphTokenLockManager') + const managerDeploy = await deploy(managerSaveName, { + from: deployer, + args: [tokenAddress, masterCopyDeploy.address], + log: true, + contract: 'GraphTokenLockManager', + }) + + // -- Fund -- + + if (await askConfirm('Do you want to fund the manager?')) { + const fundAmount = parseEther('100000000') + logger.info(`Funding ${managerDeploy.address} with ${formatEther(fundAmount)} GRT...`) + + // Approve + const grt = (await hre.ethers.getContractAt('GraphTokenMock', tokenAddress)) as GraphTokenMock + await grt.approve(managerDeploy.address, fundAmount) + + // Deposit + const manager = (await hre.ethers.getContractAt( + 'GraphTokenLockManager', + managerDeploy.address, + )) as GraphTokenLockManager + await manager.deposit(fundAmount) + + logger.success('Done!') + } +} + +func.tags = ['manager', 'l1', 'l1-manager', 'l1-wallet'] + +export default func diff --git a/packages/token-distribution/deploy/3_l2_wallet.ts b/packages/token-distribution/deploy/3_l2_wallet.ts new file mode 100644 index 000000000..36679613c --- /dev/null +++ b/packages/token-distribution/deploy/3_l2_wallet.ts @@ -0,0 +1,26 @@ +import consola from 'consola' +import '@nomiclabs/hardhat-ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction, DeployOptions } from 'hardhat-deploy/types' + +import { getDeploymentName } from './lib/utils' + +const logger = consola.create({}) + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const deploy = (name: string, options: DeployOptions) => hre.deployments.deploy(name, options) + const { deployer } = await hre.getNamedAccounts() + + // Deploy the master copy of GraphTokenLockWallet + logger.info('Deploying L2GraphTokenLockWallet master copy...') + const masterCopySaveName = await getDeploymentName('L2GraphTokenLockWallet') + await deploy(masterCopySaveName, { + from: deployer, + log: true, + contract: 'L2GraphTokenLockWallet', + }) +} + +func.tags = ['l2-wallet', 'l2'] + +export default func diff --git a/packages/token-distribution/deploy/4_l1_transfer_tool.ts b/packages/token-distribution/deploy/4_l1_transfer_tool.ts new file mode 100644 index 000000000..125483f56 --- /dev/null +++ b/packages/token-distribution/deploy/4_l1_transfer_tool.ts @@ -0,0 +1,78 @@ +import consola from 'consola' + +import '@nomiclabs/hardhat-ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +import { getDeploymentName, promptContractAddress } from './lib/utils' +import { ethers, upgrades } from 'hardhat' +import { L1GraphTokenLockTransferTool } from '../build/typechain/contracts/L1GraphTokenLockTransferTool' +import path from 'path' +import { Artifacts } from 'hardhat/internal/artifacts' + +const logger = consola.create({}) + +const ARTIFACTS_PATH = path.resolve('build/artifacts') +const artifacts = new Artifacts(ARTIFACTS_PATH) +const l1TransferToolAbi = artifacts.readArtifactSync('L1GraphTokenLockTransferTool').abi + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployer } = await hre.getNamedAccounts() + + // Get the addresses we will use + const tokenAddress = await promptContractAddress('L1 GRT', logger) + if (!tokenAddress) { + logger.warn('No token address provided') + process.exit(1) + } + + const l2Implementation = await promptContractAddress('L2GraphTokenLockWallet implementation', logger) + if (!l2Implementation) { + logger.warn('No L2 implementation address provided') + process.exit(1) + } + + const l1Gateway = await promptContractAddress('L1 token gateway', logger) + if (!l1Gateway) { + logger.warn('No L1 gateway address provided') + process.exit(1) + } + + const l1Staking = await promptContractAddress('L1 Staking', logger) + if (!l1Staking) { + logger.warn('No L1 Staking address provided') + process.exit(1) + } + + let owner = await promptContractAddress('owner (optional)', logger) + if (!owner) { + owner = deployer + logger.warn(`No owner address provided, will use the deployer address as owner: ${owner}`) + } + + // Deploy the L1GraphTokenLockTransferTool with a proxy. + // hardhat-deploy doesn't get along with constructor arguments in the implementation + // combined with an OpenZeppelin transparent proxy, so we need to do this using + // the OpenZeppelin hardhat-upgrades tooling, and save the deployment manually. + + // TODO modify this to use upgradeProxy if a deployment already exists? + logger.info('Deploying L1GraphTokenLockTransferTool proxy...') + const transferToolFactory = await ethers.getContractFactory('L1GraphTokenLockTransferTool') + const transferTool = (await upgrades.deployProxy(transferToolFactory, [owner], { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [tokenAddress, l2Implementation, l1Gateway, l1Staking], + })) as L1GraphTokenLockTransferTool + + // Save the deployment + const deploymentName = await getDeploymentName('L1GraphTokenLockTransferTool') + await hre.deployments.save(deploymentName, { + abi: l1TransferToolAbi, + address: transferTool.address, + transactionHash: transferTool.deployTransaction.hash, + }) +} + +func.tags = ['l1', 'l1-transfer-tool'] + +export default func diff --git a/packages/token-distribution/deploy/5_l2_manager.ts b/packages/token-distribution/deploy/5_l2_manager.ts new file mode 100644 index 000000000..93016663f --- /dev/null +++ b/packages/token-distribution/deploy/5_l2_manager.ts @@ -0,0 +1,79 @@ +import consola from 'consola' +import { utils } from 'ethers' + +import '@nomiclabs/hardhat-ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction, DeployOptions } from 'hardhat-deploy/types' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { askConfirm, getDeploymentName, promptContractAddress } from './lib/utils' +import { L2GraphTokenLockManager } from '../build/typechain/contracts/L2GraphTokenLockManager' + +const { parseEther, formatEther } = utils + +const logger = consola.create({}) + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const deploy = (name: string, options: DeployOptions) => hre.deployments.deploy(name, options) + const { deployer } = await hre.getNamedAccounts() + + // -- Graph Token -- + + // Get the token address we will use + const tokenAddress = await promptContractAddress('L2 GRT', logger) + if (!tokenAddress) { + logger.warn('No token address provided') + process.exit(1) + } + + const l2Gateway = await promptContractAddress('L2 Gateway', logger) + if (!l2Gateway) { + logger.warn('No L2 Gateway address provided') + process.exit(1) + } + + const l1TransferTool = await promptContractAddress('L1 Transfer Tool', logger) + if (!l1TransferTool) { + logger.warn('No L1 Transfer Tool address provided') + process.exit(1) + } + + // -- L2 Token Lock Manager -- + // Get the deployed L2GraphTokenLockWallet master copy address + const masterCopyDeploy = await hre.deployments.get('L2GraphTokenLockWallet') + + logger.info(`Using L2GraphTokenLockWallet at address: ${masterCopyDeploy.address}`) + // Deploy the Manager that uses the master copy to clone contracts + logger.info('Deploying L2GraphTokenLockManager...') + const managerSaveName = await getDeploymentName('L2GraphTokenLockManager') + const managerDeploy = await deploy(managerSaveName, { + from: deployer, + args: [tokenAddress, masterCopyDeploy.address, l2Gateway, l1TransferTool], + log: true, + contract: 'L2GraphTokenLockManager', + }) + + // -- Fund -- + + if (await askConfirm('Do you want to fund the L2 manager?')) { + const fundAmount = parseEther('100000000') + logger.info(`Funding ${managerDeploy.address} with ${formatEther(fundAmount)} GRT...`) + + // Approve + const grt = (await hre.ethers.getContractAt('GraphTokenMock', tokenAddress)) as GraphTokenMock + await grt.approve(managerDeploy.address, fundAmount) + + // Deposit + const manager = (await hre.ethers.getContractAt( + 'L2GraphTokenLockManager', + managerDeploy.address, + )) as L2GraphTokenLockManager + await manager.deposit(fundAmount) + + logger.success('Done!') + } +} + +func.tags = ['l2-manager', 'l2'] + +export default func diff --git a/packages/token-distribution/deploy/6_l2_transfer_tool.ts b/packages/token-distribution/deploy/6_l2_transfer_tool.ts new file mode 100644 index 000000000..f449ebe84 --- /dev/null +++ b/packages/token-distribution/deploy/6_l2_transfer_tool.ts @@ -0,0 +1,66 @@ +import consola from 'consola' + +import '@nomiclabs/hardhat-ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +import { getDeploymentName, promptContractAddress } from './lib/utils' +import { ethers, upgrades } from 'hardhat' +import { L1GraphTokenLockTransferTool } from '../build/typechain/contracts/L1GraphTokenLockTransferTool' +import path from 'path' +import { Artifacts } from 'hardhat/internal/artifacts' + +const logger = consola.create({}) + +const ARTIFACTS_PATH = path.resolve('build/artifacts') +const artifacts = new Artifacts(ARTIFACTS_PATH) +const l2TransferToolAbi = artifacts.readArtifactSync('L2GraphTokenLockTransferTool').abi + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + // -- Graph Token -- + + // Get the addresses we will use + const tokenAddress = await promptContractAddress('L2 GRT', logger) + if (!tokenAddress) { + logger.warn('No token address provided') + process.exit(1) + } + + const l2Gateway = await promptContractAddress('L2 token gateway', logger) + if (!l2Gateway) { + logger.warn('No L2 gateway address provided') + process.exit(1) + } + + const l1Token = await promptContractAddress('L1 GRT', logger) + if (!l1Token) { + logger.warn('No L1 GRT address provided') + process.exit(1) + } + + // Deploy the L2GraphTokenLockTransferTool with a proxy. + // hardhat-deploy doesn't get along with constructor arguments in the implementation + // combined with an OpenZeppelin transparent proxy, so we need to do this using + // the OpenZeppelin hardhat-upgrades tooling, and save the deployment manually. + + // TODO modify this to use upgradeProxy if a deployment already exists? + logger.info('Deploying L2GraphTokenLockTransferTool proxy...') + const transferToolFactory = await ethers.getContractFactory('L2GraphTokenLockTransferTool') + const transferTool = (await upgrades.deployProxy(transferToolFactory, [], { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [tokenAddress, l2Gateway, l1Token], + })) as L1GraphTokenLockTransferTool + + // Save the deployment + const deploymentName = await getDeploymentName('L2GraphTokenLockTransferTool') + await hre.deployments.save(deploymentName, { + abi: l2TransferToolAbi, + address: transferTool.address, + transactionHash: transferTool.deployTransaction.hash, + }) +} + +func.tags = ['l2', 'l2-transfer-tool'] + +export default func diff --git a/packages/token-distribution/deploy/lib/utils.ts b/packages/token-distribution/deploy/lib/utils.ts new file mode 100644 index 000000000..afc38555b --- /dev/null +++ b/packages/token-distribution/deploy/lib/utils.ts @@ -0,0 +1,41 @@ +import { Consola } from 'consola' +import inquirer from 'inquirer' +import { utils } from 'ethers' + +import '@nomiclabs/hardhat-ethers' + +const { getAddress } = utils + +export const askConfirm = async (message: string) => { + const res = await inquirer.prompt({ + name: 'confirm', + type: 'confirm', + message, + }) + return res.confirm ? res.confirm as boolean : false +} + +export const promptContractAddress = async (name: string, logger: Consola): Promise => { + const res1 = await inquirer.prompt({ + name: 'contract', + type: 'input', + message: `What is the ${name} address?`, + }) + + try { + return getAddress(res1.contract) + } catch (err) { + logger.error(err) + return null + } +} + +export const getDeploymentName = async (defaultName: string): Promise => { + const res = await inquirer.prompt({ + name: 'deployment-name', + type: 'input', + default: defaultName, + message: 'Save deployment as?', + }) + return res['deployment-name'] as string +} diff --git a/packages/token-distribution/deployments/arbitrum-goerli/.chainId b/packages/token-distribution/deployments/arbitrum-goerli/.chainId new file mode 100644 index 000000000..16be23a37 --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-goerli/.chainId @@ -0,0 +1 @@ +421613 \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockManager-Testnet.json b/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockManager-Testnet.json new file mode 100644 index 000000000..a26292a14 --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockManager-Testnet.json @@ -0,0 +1,1161 @@ +{ + "address": "0xF3b617e0c966329363e78c266361794e84223313", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1TransferTool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Address", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedTokensReceivedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "TokenLockCreatedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1TransferTool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l1WalletToL2Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletToL1Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x2bb1e86bcd24dde8f082234f452f48613cacf5f8ed49b7e7754ad12b94e819ac", + "receipt": { + "to": null, + "from": "0xB15599AC1261C4828Ac7E66383ae520655d3D300", + "contractAddress": "0xF3b617e0c966329363e78c266361794e84223313", + "transactionIndex": 1, + "gasUsed": "3854618", + "logsBloom": "0x00000000000000000000000000020000000004010000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000400000000000040000020000000000000000000800000000000000000001000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000010000000000002000000002000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000000100000000000000000", + "blockHash": "0x17ed68b2e729840cca04decf7c536a25530754b7b536028e9e900c538bac6fe6", + "transactionHash": "0x2bb1e86bcd24dde8f082234f452f48613cacf5f8ed49b7e7754ad12b94e819ac", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 30437370, + "transactionHash": "0x2bb1e86bcd24dde8f082234f452f48613cacf5f8ed49b7e7754ad12b94e819ac", + "address": "0xF3b617e0c966329363e78c266361794e84223313", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b15599ac1261c4828ac7e66383ae520655d3d300" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x17ed68b2e729840cca04decf7c536a25530754b7b536028e9e900c538bac6fe6" + }, + { + "transactionIndex": 1, + "blockNumber": 30437370, + "transactionHash": "0x2bb1e86bcd24dde8f082234f452f48613cacf5f8ed49b7e7754ad12b94e819ac", + "address": "0xF3b617e0c966329363e78c266361794e84223313", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x000000000000000000000000c93df24c3a1ebeccd0e5d41198460081cfb38c49" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x17ed68b2e729840cca04decf7c536a25530754b7b536028e9e900c538bac6fe6" + } + ], + "blockNumber": 30437370, + "cumulativeGasUsed": "3854618", + "status": 1, + "byzantium": true + }, + "args": [ + "0x18C924BD5E8b83b47EFaDD632b7178E2Fd36073D", + "0xc93df24c3A1ebeCcd0e5D41198460081CFB38c49", + "0xef2757855d2802bA53733901F90C91645973f743", + "0xa725CF32c367778CFF2ba7089Ab4e941BDD88612" + ], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Gateway\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l1TransferTool\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Address\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LockedTokensReceivedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"}],\"name\":\"TokenLockCreatedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1TransferTool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l1WalletToL2Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l2WalletToL1Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"LockedTokensReceivedFromL1(address,address,uint256)\":{\"details\":\"Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)\"},\"TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)\":{\"details\":\"Event emitted when a wallet is received and created from L1\"}},\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Address of the L2 GRT token contract\",\"_l1TransferTool\":\"Address of the L1 transfer tool contract (in L1, without aliasing)\",\"_l2Gateway\":\"Address of the L2GraphTokenGateway contract\",\"_masterCopy\":\"Address of the master copy of the L2GraphTokenLockWallet implementation\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"onTokenTransfer(address,uint256,bytes)\":{\"details\":\"This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.\",\"params\":{\"_amount\":\"Amount of tokens received\",\"_data\":\"Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\",\"_from\":\"Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor for the L2GraphTokenLockManager contract.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"l1TransferTool()\":{\"notice\":\"Address of the L1 transfer tool contract (in L1, no aliasing)\"},\"l1WalletToL2Wallet(address)\":{\"notice\":\"Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address\"},\"l2Gateway()\":{\"notice\":\"Address of the L2GraphTokenGateway\"},\"l2WalletToL1Wallet(address)\":{\"notice\":\"Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address\"},\"onTokenTransfer(address,uint256,bytes)\":{\"notice\":\"This function is called by the L2GraphTokenGateway when tokens are sent from L1.\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockManager.sol\":\"L2GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200499938038062004999833981810160405281019062000037919062000410565b838360006200004b6200022860201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001539062000586565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ae816200023060201b60201c565b50508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250505050505062000635565b600033905090565b620002406200022860201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1662000266620003b960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620002bf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b69062000564565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000332576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003299062000542565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600081519050620003f38162000601565b92915050565b6000815190506200040a816200061b565b92915050565b600080600080608085870312156200042757600080fd5b60006200043787828801620003f9565b94505060206200044a87828801620003e2565b93505060406200045d87828801620003e2565b92505060606200047087828801620003e2565b91505092959194509250565b60006200048b601983620005a8565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000620004cd602083620005a8565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200050f601483620005a8565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b600060208201905081810360008301526200055d816200047c565b9050919050565b600060208201905081810360008301526200057f81620004be565b9050919050565b60006020820190508181036000830152620005a18162000500565b9050919050565b600082825260208201905092915050565b6000620005c682620005e1565b9050919050565b6000620005da82620005b9565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200060c81620005b9565b81146200061857600080fd5b50565b6200062681620005cd565b81146200063257600080fd5b50565b60805160601c60a05160601c61433062000669600039806109195280611280525080610fc952806111f252506143306000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "devdoc": { + "events": { + "LockedTokensReceivedFromL1(address,address,uint256)": { + "details": "Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)" + }, + "TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)": { + "details": "Event emitted when a wallet is received and created from L1" + } + }, + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Address of the L2 GRT token contract", + "_l1TransferTool": "Address of the L1 transfer tool contract (in L1, without aliasing)", + "_l2Gateway": "Address of the L2GraphTokenGateway contract", + "_masterCopy": "Address of the master copy of the L2GraphTokenLockWallet implementation" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "onTokenTransfer(address,uint256,bytes)": { + "details": "This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.", + "params": { + "_amount": "Amount of tokens received", + "_data": "Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct", + "_from": "Address of the sender in L1, which must be the L1GraphTokenLockTransferTool" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor for the L2GraphTokenLockManager contract." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "l1TransferTool()": { + "notice": "Address of the L1 transfer tool contract (in L1, no aliasing)" + }, + "l1WalletToL2Wallet(address)": { + "notice": "Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address" + }, + "l2Gateway()": { + "notice": "Address of the L2GraphTokenGateway" + }, + "l2WalletToL1Wallet(address)": { + "notice": "Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address" + }, + "onTokenTransfer(address,uint256,bytes)": { + "notice": "This function is called by the L2GraphTokenGateway when tokens are sent from L1." + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 6154, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l1WalletToL2Wallet", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 6159, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l2WalletToL1Wallet", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockTransferTool.json b/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockTransferTool.json new file mode 100644 index 000000000..8f2a27976 --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockTransferTool.json @@ -0,0 +1,110 @@ +{ + "address": "0xc1A9C2E76171e64Cd5669B3E89D9A25a6b0FAfB7", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "contract ITokenGateway", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1GraphToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedFundsSentToL1", + "type": "event" + }, + { + "inputs": [], + "name": "graphToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1GraphToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "contract ITokenGateway", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawToL1Locked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x4c0fdb3290d0e247de1d0863bc2a7b13ea9414a86e5bfe94f1e2eba7c5c47f70" +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockWallet.json b/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockWallet.json new file mode 100644 index 000000000..9b76d53e0 --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockWallet.json @@ -0,0 +1,1156 @@ +{ + "address": "0xc93df24c3A1ebeCcd0e5D41198460081CFB38c49", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + } + ], + "internalType": "struct L2GraphTokenLockManager.TransferredWalletData", + "name": "_walletData", + "type": "tuple" + } + ], + "name": "initializeFromL1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x3342cbf5abb884c865fcdb43dda39ebdde525df610352ef732cff970efb0fdc9", + "receipt": { + "to": null, + "from": "0xB15599AC1261C4828Ac7E66383ae520655d3D300", + "contractAddress": "0xc93df24c3A1ebeCcd0e5D41198460081CFB38c49", + "transactionIndex": 1, + "gasUsed": "4086023", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf5d75eaf427f71f4729137e3c372fa1fc040578674861fa4eb188d692d47b8a6", + "transactionHash": "0x3342cbf5abb884c865fcdb43dda39ebdde525df610352ef732cff970efb0fdc9", + "logs": [], + "blockNumber": 30437051, + "cumulativeGasUsed": "4086023", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"}],\"internalType\":\"struct L2GraphTokenLockManager.TransferredWalletData\",\"name\":\"_walletData\",\"type\":\"tuple\"}],\"name\":\"initializeFromL1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. This L2 variant includes a special initializer so that it can be created from a wallet's data received from L1. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1, so releasing surplus tokens might also only be possible by bridging tokens back to L1. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockWallet.sol\":\"L2GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506148f5806100206000396000f3fe6080604052600436106102605760003560e01c80637bdf05af11610144578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610bc7578063e8dda6f514610bf0578063e97d87d514610c1b578063ebbab99214610c46578063f2fde38b14610c71578063fc0c546a14610c9a576102a0565b8063bc0163c114610af4578063bd896dcb14610b1f578063ce845d1d14610b48578063d0ebdbe714610b73578063d18e81b314610b9c576102a0565b80638da5cb5b116101085780638da5cb5b14610a0857806391f7cfb914610a33578063a4caeb4214610a5e578063b0d1818c14610a89578063b470aade14610ab2578063b6549f7514610add576102a0565b80637bdf05af1461095957806386d00e021461098457806386d1a69f146109af578063872a7810146109c65780638a5bdf5c146109f1576102a0565b806338af3eed116101dd578063481c6a75116101a1578063481c6a751461087f5780635051a5ec146108aa5780635b940081146108d557806360e7994414610900578063715018a61461091757806378e979251461092e576102a0565b806338af3eed146107a8578063392e53cd146107d3578063398057a3146107fe57806344b1231f1461082957806345d30a1714610854576102a0565b806320dc203d1161022457806320dc203d146106e75780632a627814146107105780632bc9ed02146107275780633197cbb61461075257806337aeb0861461077d576102a0565b8063029c6c9f14610624578063060406181461064f5780630b80f7771461067a5780630dff24d5146106915780630fb5a6b4146106bc576102a0565b366102a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610297906141f3565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610327906143d3565b60405180910390fd5b60003414610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036a90614213565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103f49190614165565b60206040518083038186803b15801561040c57600080fd5b505afa158015610420573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610444919061338f565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ad906144d3565b60405180910390fd5b60006104c0610cc5565b9050610511826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d77565b506001600281111561051f57fe5b603b60009054906101000a900460ff16600281111561053a57fe5b141561062057600061054a610cc5565b90508181101561058c5760006105698284610dc190919063ffffffff16565b905061058081603f54610e1190919063ffffffff16565b603f81905550506105d2565b60006105a18383610dc190919063ffffffff16565b9050603f548110156105c7576105c281603f54610dc190919063ffffffff16565b6105ca565b60005b603f81905550505b6105da610e66565b603f54111561061e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061590614433565b60405180910390fd5b505b5050005b34801561063057600080fd5b50610639610ed5565b6040516106469190614673565b60405180910390f35b34801561065b57600080fd5b50610664610ef3565b6040516106719190614673565b60405180910390f35b34801561068657600080fd5b5061068f610f2e565b005b34801561069d57600080fd5b506106a661109b565b6040516106b39190614673565b60405180910390f35b3480156106c857600080fd5b506106d16110e2565b6040516106de9190614673565b60405180910390f35b3480156106f357600080fd5b5061070e600480360381019061070991906134a8565b611100565b005b34801561071c57600080fd5b5061072561129b565b005b34801561073357600080fd5b5061073c611500565b604051610749919061414a565b60405180910390f35b34801561075e57600080fd5b50610767611513565b6040516107749190614673565b60405180910390f35b34801561078957600080fd5b50610792611519565b60405161079f9190614673565b60405180910390f35b3480156107b457600080fd5b506107bd61151f565b6040516107ca91906140dd565b60405180910390f35b3480156107df57600080fd5b506107e8611545565b6040516107f5919061414a565b60405180910390f35b34801561080a57600080fd5b50610813611558565b6040516108209190614673565b60405180910390f35b34801561083557600080fd5b5061083e610e66565b60405161084b9190614673565b60405180910390f35b34801561086057600080fd5b5061086961155e565b6040516108769190614673565b60405180910390f35b34801561088b57600080fd5b50610894611564565b6040516108a1919061419b565b60405180910390f35b3480156108b657600080fd5b506108bf61158a565b6040516108cc919061414a565b60405180910390f35b3480156108e157600080fd5b506108ea61159d565b6040516108f79190614673565b60405180910390f35b34801561090c57600080fd5b506109156116a8565b005b34801561092357600080fd5b5061092c6118ee565b005b34801561093a57600080fd5b50610943611a3a565b6040516109509190614673565b60405180910390f35b34801561096557600080fd5b5061096e611a40565b60405161097b9190614673565b60405180910390f35b34801561099057600080fd5b50610999611a7c565b6040516109a69190614673565b60405180910390f35b3480156109bb57600080fd5b506109c4611a82565b005b3480156109d257600080fd5b506109db611c5e565b6040516109e891906141b6565b60405180910390f35b3480156109fd57600080fd5b50610a06611c71565b005b348015610a1457600080fd5b50610a1d611d4a565b604051610a2a91906140dd565b60405180910390f35b348015610a3f57600080fd5b50610a48611d73565b604051610a559190614673565b60405180910390f35b348015610a6a57600080fd5b50610a73611dd1565b604051610a809190614673565b60405180910390f35b348015610a9557600080fd5b50610ab06004803603810190610aab9190613562565b611dd7565b005b348015610abe57600080fd5b50610ac7611fd6565b604051610ad49190614673565b60405180910390f35b348015610ae957600080fd5b50610af2611ff9565b005b348015610b0057600080fd5b50610b09612291565b604051610b169190614673565b60405180910390f35b348015610b2b57600080fd5b50610b466004803603810190610b4191906133b8565b6122c3565b005b348015610b5457600080fd5b50610b5d610cc5565b604051610b6a9190614673565b60405180910390f35b348015610b7f57600080fd5b50610b9a6004803603810190610b959190613366565b6122eb565b005b348015610ba857600080fd5b50610bb1612385565b604051610bbe9190614673565b60405180910390f35b348015610bd357600080fd5b50610bee6004803603810190610be99190613366565b61238d565b005b348015610bfc57600080fd5b50610c05612508565b604051610c129190614673565b60405180910390f35b348015610c2757600080fd5b50610c3061250e565b604051610c3d9190614673565b60405180910390f35b348015610c5257600080fd5b50610c5b612514565b604051610c689190614673565b60405180910390f35b348015610c7d57600080fd5b50610c986004803603810190610c939190613366565b612536565b005b348015610ca657600080fd5b50610caf6126f1565b604051610cbc9190614180565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d2291906140dd565b60206040518083038186803b158015610d3a57600080fd5b505afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d72919061358b565b905090565b6060610db983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612717565b905092915050565b600082821115610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90614333565b60405180910390fd5b818303905092915050565b600080828401905083811015610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e53906142b3565b60405180910390fd5b8091505092915050565b6000600280811115610e7457fe5b603b60009054906101000a900460ff166002811115610e8f57fe5b1415610e9f576035549050610ed2565b6000603a54118015610eb95750603a54610eb7612385565b105b15610ec75760009050610ed2565b610ecf611d73565b90505b90565b6000610eee60385460355461272f90919063ffffffff16565b905090565b6000610f296001610f1b610f05611fd6565b610f0d611a40565b61272f90919063ffffffff16565b610e1190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb390614493565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514611012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100990614313565b60405180910390fd5b61106d61101d611d4a565b611025610cc5565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b6000806110a6610cc5565b905060006110b2612291565b9050808211156110d8576110cf8183610dc190919063ffffffff16565b925050506110df565b6000925050505b90565b60006110fb603654603754610dc190919063ffffffff16565b905090565b603b60029054906101000a900460ff1615611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114790614533565b60405180910390fd5b6001603b60026101000a81548160ff0219169083151502179055506111868160200160208101906111819190613366565b61280b565b8060400160208101906111999190613366565b603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806060013560358190555080608001356036819055508060a0013560378190555060016038819055506001603b60036101000a81548160ff0219169083151502179055508060a001356039819055506002603b60006101000a81548160ff0219169083600281111561128857fe5b0217905550611296836128a9565b505050565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132290614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561139557600080fd5b505afa1580156113a9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113d291906134f8565b905060005b81518110156114d057603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061142a57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b8152600401611470929190614121565b602060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c29190613539565b5080806001019150506113d7565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156115ab57fe5b603b60009054906101000a900460ff1660028111156115c657fe5b14156115db576115d4612a27565b90506116a5565b60006039541180156115f557506039546115f3612385565b105b1561160357600090506116a5565b6001600281111561161057fe5b603b60009054906101000a900460ff16600281111561162b57fe5b14801561163a57506000603a54115b801561164e5750603a5461164c612385565b105b1561165c57600090506116a5565b600061168e603f54611680603c54611672611d73565b610dc190919063ffffffff16565b610dc190919063ffffffff16565b90506116a161169b610cc5565b82612ae1565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172f90614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906117df91906134f8565b905060005b81518110156118be57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061183757fe5b602002602001015160006040518363ffffffff1660e01b815260040161185e9291906140f8565b602060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b09190613539565b5080806001019150506117e4565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197390614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b600080611a4b612385565b90506036548111611a60576000915050611a79565b611a7560365482610dc190919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0990614593565b60405180910390fd5b6000611b1c61159d565b905060008111611b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b58906145f3565b60405180910390fd5b611b7681603c54610e1190919063ffffffff16565b603c81905550611beb603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611c539190614673565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890614593565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611d7e612385565b9050603654811015611d94576000915050611dce565b603754811115611da957603554915050611dce565b611dca611db4610ed5565b611dbc612514565b612afa90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5e90614593565b60405180910390fd5b60008111611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea190614413565b60405180910390fd5b80611eb361109b565b1015611ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eeb90614513565b60405180910390fd5b611f63603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611fcb9190614673565b60405180910390a250565b6000611ff4603854611fe66110e2565b61272f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614493565b60405180910390fd5b6001600281111561209457fe5b603b60009054906101000a900460ff1660028111156120af57fe5b146120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614553565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213c90614653565b60405180910390fd5b6000612163612152610e66565b603554610dc190919063ffffffff16565b9050600081116121a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219f906142d3565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061221e6121d5611d4a565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516122869190614673565b60405180910390a250565b60006122be603d546122b0603c54603554610dc190919063ffffffff16565b610dc190919063ffffffff16565b905090565b6122d58a8a8a8a8a8a8a8a8a8a612b6a565b6122de8b6128a9565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237090614493565b60405180910390fd5b612382816128a9565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461241d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161241490614593565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561248d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612484906143b3565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d816040516124fd91906140dd565b60405180910390a150565b603f5481565b60395481565b60006125316001612523610ef3565b610dc190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bb90614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262b90614293565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606127268484600085612ff4565b90509392505050565b6000808211612773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276a90614393565b60405180910390fd5b81838161277c57fe5b04905092915050565b6128068363a9059cbb60e01b84846040516024016127a4929190614121565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613109565b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291090614573565b60405180910390fd5b612922816131d0565b612961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612958906143f3565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b600080603954118015612a425750603954612a40612385565b105b15612a505760009050612ade565b60016002811115612a5d57fe5b603b60009054906101000a900460ff166002811115612a7857fe5b148015612a8757506000603a54115b8015612a9b5750603a54612a99612385565b105b15612aa95760009050612ade565b6000612ac7603c54612ab9611d73565b610dc190919063ffffffff16565b9050612ada612ad4610cc5565b82612ae1565b9150505b90565b6000818310612af05781612af2565b825b905092915050565b600080831415612b0d5760009050612b64565b6000828402905082848281612b1e57fe5b0414612b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5690614473565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff1615612bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb190614533565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c21906142f3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190614633565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0190614613565b60405180910390fd5b60008711612d4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4490614373565b60405180910390fd5b6000861415612d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d88906144b3565b60405180910390fd5b848610612dd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dca90614253565b60405180910390fd5b6001841015612e17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0e90614453565b60405180910390fd5b60006002811115612e2457fe5b816002811115612e3057fe5b1415612e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e6890614273565b60405180910390fd5b848310612eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eaa906145b3565b60405180910390fd5b848210612ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eec90614233565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612f198a61280b565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612fe357fe5b021790555050505050505050505050565b606082471015613039576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161303090614353565b60405180910390fd5b613042856131d0565b613081576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613078906144f3565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516130ab91906140c6565b60006040518083038185875af1925050503d80600081146130e8576040519150601f19603f3d011682016040523d82523d6000602084013e6130ed565b606091505b50915091506130fd8282866131e3565b92505050949350505050565b606061316b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166127179092919063ffffffff16565b90506000815111156131cb578080602001905181019061318b9190613539565b6131ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131c1906145d3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b606083156131f357829050613243565b6000835111156132065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323a91906141d1565b60405180910390fd5b9392505050565b6000813590506132598161486a565b92915050565b60008151905061326e8161486a565b92915050565b600082601f83011261328557600080fd5b8151613298613293826146bf565b61468e565b915081818352602084019350602081019050838560208402820111156132bd57600080fd5b60005b838110156132ed57816132d3888261325f565b8452602084019350602083019250506001810190506132c0565b5050505092915050565b60008151905061330681614881565b92915050565b60008135905061331b81614898565b92915050565b600060c0828403121561333357600080fd5b81905092915050565b60008135905061334b816148a8565b92915050565b600081519050613360816148a8565b92915050565b60006020828403121561337857600080fd5b60006133868482850161324a565b91505092915050565b6000602082840312156133a157600080fd5b60006133af8482850161325f565b91505092915050565b60008060008060008060008060008060006101608c8e0312156133da57600080fd5b60006133e88e828f0161324a565b9b505060206133f98e828f0161324a565b9a5050604061340a8e828f0161324a565b995050606061341b8e828f0161324a565b985050608061342c8e828f0161333c565b97505060a061343d8e828f0161333c565b96505060c061344e8e828f0161333c565b95505060e061345f8e828f0161333c565b9450506101006134718e828f0161333c565b9350506101206134838e828f0161333c565b9250506101406134958e828f0161330c565b9150509295989b509295989b9093969950565b600080600061010084860312156134be57600080fd5b60006134cc8682870161324a565b93505060206134dd8682870161324a565b92505060406134ee86828701613321565b9150509250925092565b60006020828403121561350a57600080fd5b600082015167ffffffffffffffff81111561352457600080fd5b61353084828501613274565b91505092915050565b60006020828403121561354b57600080fd5b6000613559848285016132f7565b91505092915050565b60006020828403121561357457600080fd5b60006135828482850161333c565b91505092915050565b60006020828403121561359d57600080fd5b60006135ab84828501613351565b91505092915050565b6135bd8161471d565b82525050565b6135cc8161472f565b82525050565b6135db8161473b565b82525050565b60006135ec826146eb565b6135f68185614701565b9350613606818560208601614810565b80840191505092915050565b61361b816147a4565b82525050565b61362a816147c8565b82525050565b613639816147ec565b82525050565b613648816147fe565b82525050565b6000613659826146f6565b613663818561470c565b9350613673818560208601614810565b61367c81614845565b840191505092915050565b600061369460088361470c565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b60006136d4601b8361470c565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b600061371460228361470c565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061377a60158361470c565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b60006137ba601e8361470c565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006137fa60268361470c565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613860601b8361470c565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006138a0601c8361470c565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006138e060148361470c565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613920601f8361470c565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613960601e8361470c565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006139a060268361470c565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a06601d8361470c565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b6000613a46601a8361470c565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b6000613a8660118361470c565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b6000613ac660138361470c565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b6000613b06601a8361470c565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b6000613b4660158361470c565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613b8660298361470c565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bec601f8361470c565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b6000613c2c60218361470c565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c9260208361470c565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613cd260168361470c565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613d1260158361470c565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613d52601d8361470c565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613d9260248361470c565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df860138361470c565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613e3860198361470c565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613e7860178361470c565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613eb860058361470c565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613ef8602a8361470c565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613f5e602a8361470c565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fc4601e8361470c565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b600061400460148361470c565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000614044601a8361470c565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000614084600f8361470c565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b6140c08161479a565b82525050565b60006140d282846135e1565b915081905092915050565b60006020820190506140f260008301846135b4565b92915050565b600060408201905061410d60008301856135b4565b61411a602083018461363f565b9392505050565b600060408201905061413660008301856135b4565b61414360208301846140b7565b9392505050565b600060208201905061415f60008301846135c3565b92915050565b600060208201905061417a60008301846135d2565b92915050565b60006020820190506141956000830184613612565b92915050565b60006020820190506141b06000830184613621565b92915050565b60006020820190506141cb6000830184613630565b92915050565b600060208201905081810360008301526141eb818461364e565b905092915050565b6000602082019050818103600083015261420c81613687565b9050919050565b6000602082019050818103600083015261422c816136c7565b9050919050565b6000602082019050818103600083015261424c81613707565b9050919050565b6000602082019050818103600083015261426c8161376d565b9050919050565b6000602082019050818103600083015261428c816137ad565b9050919050565b600060208201905081810360008301526142ac816137ed565b9050919050565b600060208201905081810360008301526142cc81613853565b9050919050565b600060208201905081810360008301526142ec81613893565b9050919050565b6000602082019050818103600083015261430c816138d3565b9050919050565b6000602082019050818103600083015261432c81613913565b9050919050565b6000602082019050818103600083015261434c81613953565b9050919050565b6000602082019050818103600083015261436c81613993565b9050919050565b6000602082019050818103600083015261438c816139f9565b9050919050565b600060208201905081810360008301526143ac81613a39565b9050919050565b600060208201905081810360008301526143cc81613a79565b9050919050565b600060208201905081810360008301526143ec81613ab9565b9050919050565b6000602082019050818103600083015261440c81613af9565b9050919050565b6000602082019050818103600083015261442c81613b39565b9050919050565b6000602082019050818103600083015261444c81613b79565b9050919050565b6000602082019050818103600083015261446c81613bdf565b9050919050565b6000602082019050818103600083015261448c81613c1f565b9050919050565b600060208201905081810360008301526144ac81613c85565b9050919050565b600060208201905081810360008301526144cc81613cc5565b9050919050565b600060208201905081810360008301526144ec81613d05565b9050919050565b6000602082019050818103600083015261450c81613d45565b9050919050565b6000602082019050818103600083015261452c81613d85565b9050919050565b6000602082019050818103600083015261454c81613deb565b9050919050565b6000602082019050818103600083015261456c81613e2b565b9050919050565b6000602082019050818103600083015261458c81613e6b565b9050919050565b600060208201905081810360008301526145ac81613eab565b9050919050565b600060208201905081810360008301526145cc81613eeb565b9050919050565b600060208201905081810360008301526145ec81613f51565b9050919050565b6000602082019050818103600083015261460c81613fb7565b9050919050565b6000602082019050818103600083015261462c81613ff7565b9050919050565b6000602082019050818103600083015261464c81614037565b9050919050565b6000602082019050818103600083015261466c81614077565b9050919050565b600060208201905061468860008301846140b7565b92915050565b6000604051905081810181811067ffffffffffffffff821117156146b5576146b4614843565b5b8060405250919050565b600067ffffffffffffffff8211156146da576146d9614843565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006147288261477a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061477582614856565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006147af826147b6565b9050919050565b60006147c18261477a565b9050919050565b60006147d3826147da565b9050919050565b60006147e58261477a565b9050919050565b60006147f782614767565b9050919050565b60006148098261479a565b9050919050565b60005b8381101561482e578082015181840152602081019050614813565b8381111561483d576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061486757614866614843565b5b50565b6148738161471d565b811461487e57600080fd5b50565b61488a8161472f565b811461489557600080fd5b50565b600381106148a557600080fd5b50565b6148b18161479a565b81146148bc57600080fd5b5056fea2646970667358221220e7181b2ba4d1c3bb9e57d12c063690ecc18fa07966017865e716378e6ce1068c64736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102605760003560e01c80637bdf05af11610144578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610bc7578063e8dda6f514610bf0578063e97d87d514610c1b578063ebbab99214610c46578063f2fde38b14610c71578063fc0c546a14610c9a576102a0565b8063bc0163c114610af4578063bd896dcb14610b1f578063ce845d1d14610b48578063d0ebdbe714610b73578063d18e81b314610b9c576102a0565b80638da5cb5b116101085780638da5cb5b14610a0857806391f7cfb914610a33578063a4caeb4214610a5e578063b0d1818c14610a89578063b470aade14610ab2578063b6549f7514610add576102a0565b80637bdf05af1461095957806386d00e021461098457806386d1a69f146109af578063872a7810146109c65780638a5bdf5c146109f1576102a0565b806338af3eed116101dd578063481c6a75116101a1578063481c6a751461087f5780635051a5ec146108aa5780635b940081146108d557806360e7994414610900578063715018a61461091757806378e979251461092e576102a0565b806338af3eed146107a8578063392e53cd146107d3578063398057a3146107fe57806344b1231f1461082957806345d30a1714610854576102a0565b806320dc203d1161022457806320dc203d146106e75780632a627814146107105780632bc9ed02146107275780633197cbb61461075257806337aeb0861461077d576102a0565b8063029c6c9f14610624578063060406181461064f5780630b80f7771461067a5780630dff24d5146106915780630fb5a6b4146106bc576102a0565b366102a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610297906141f3565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610327906143d3565b60405180910390fd5b60003414610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036a90614213565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103f49190614165565b60206040518083038186803b15801561040c57600080fd5b505afa158015610420573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610444919061338f565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ad906144d3565b60405180910390fd5b60006104c0610cc5565b9050610511826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d77565b506001600281111561051f57fe5b603b60009054906101000a900460ff16600281111561053a57fe5b141561062057600061054a610cc5565b90508181101561058c5760006105698284610dc190919063ffffffff16565b905061058081603f54610e1190919063ffffffff16565b603f81905550506105d2565b60006105a18383610dc190919063ffffffff16565b9050603f548110156105c7576105c281603f54610dc190919063ffffffff16565b6105ca565b60005b603f81905550505b6105da610e66565b603f54111561061e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061590614433565b60405180910390fd5b505b5050005b34801561063057600080fd5b50610639610ed5565b6040516106469190614673565b60405180910390f35b34801561065b57600080fd5b50610664610ef3565b6040516106719190614673565b60405180910390f35b34801561068657600080fd5b5061068f610f2e565b005b34801561069d57600080fd5b506106a661109b565b6040516106b39190614673565b60405180910390f35b3480156106c857600080fd5b506106d16110e2565b6040516106de9190614673565b60405180910390f35b3480156106f357600080fd5b5061070e600480360381019061070991906134a8565b611100565b005b34801561071c57600080fd5b5061072561129b565b005b34801561073357600080fd5b5061073c611500565b604051610749919061414a565b60405180910390f35b34801561075e57600080fd5b50610767611513565b6040516107749190614673565b60405180910390f35b34801561078957600080fd5b50610792611519565b60405161079f9190614673565b60405180910390f35b3480156107b457600080fd5b506107bd61151f565b6040516107ca91906140dd565b60405180910390f35b3480156107df57600080fd5b506107e8611545565b6040516107f5919061414a565b60405180910390f35b34801561080a57600080fd5b50610813611558565b6040516108209190614673565b60405180910390f35b34801561083557600080fd5b5061083e610e66565b60405161084b9190614673565b60405180910390f35b34801561086057600080fd5b5061086961155e565b6040516108769190614673565b60405180910390f35b34801561088b57600080fd5b50610894611564565b6040516108a1919061419b565b60405180910390f35b3480156108b657600080fd5b506108bf61158a565b6040516108cc919061414a565b60405180910390f35b3480156108e157600080fd5b506108ea61159d565b6040516108f79190614673565b60405180910390f35b34801561090c57600080fd5b506109156116a8565b005b34801561092357600080fd5b5061092c6118ee565b005b34801561093a57600080fd5b50610943611a3a565b6040516109509190614673565b60405180910390f35b34801561096557600080fd5b5061096e611a40565b60405161097b9190614673565b60405180910390f35b34801561099057600080fd5b50610999611a7c565b6040516109a69190614673565b60405180910390f35b3480156109bb57600080fd5b506109c4611a82565b005b3480156109d257600080fd5b506109db611c5e565b6040516109e891906141b6565b60405180910390f35b3480156109fd57600080fd5b50610a06611c71565b005b348015610a1457600080fd5b50610a1d611d4a565b604051610a2a91906140dd565b60405180910390f35b348015610a3f57600080fd5b50610a48611d73565b604051610a559190614673565b60405180910390f35b348015610a6a57600080fd5b50610a73611dd1565b604051610a809190614673565b60405180910390f35b348015610a9557600080fd5b50610ab06004803603810190610aab9190613562565b611dd7565b005b348015610abe57600080fd5b50610ac7611fd6565b604051610ad49190614673565b60405180910390f35b348015610ae957600080fd5b50610af2611ff9565b005b348015610b0057600080fd5b50610b09612291565b604051610b169190614673565b60405180910390f35b348015610b2b57600080fd5b50610b466004803603810190610b4191906133b8565b6122c3565b005b348015610b5457600080fd5b50610b5d610cc5565b604051610b6a9190614673565b60405180910390f35b348015610b7f57600080fd5b50610b9a6004803603810190610b959190613366565b6122eb565b005b348015610ba857600080fd5b50610bb1612385565b604051610bbe9190614673565b60405180910390f35b348015610bd357600080fd5b50610bee6004803603810190610be99190613366565b61238d565b005b348015610bfc57600080fd5b50610c05612508565b604051610c129190614673565b60405180910390f35b348015610c2757600080fd5b50610c3061250e565b604051610c3d9190614673565b60405180910390f35b348015610c5257600080fd5b50610c5b612514565b604051610c689190614673565b60405180910390f35b348015610c7d57600080fd5b50610c986004803603810190610c939190613366565b612536565b005b348015610ca657600080fd5b50610caf6126f1565b604051610cbc9190614180565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d2291906140dd565b60206040518083038186803b158015610d3a57600080fd5b505afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d72919061358b565b905090565b6060610db983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612717565b905092915050565b600082821115610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90614333565b60405180910390fd5b818303905092915050565b600080828401905083811015610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e53906142b3565b60405180910390fd5b8091505092915050565b6000600280811115610e7457fe5b603b60009054906101000a900460ff166002811115610e8f57fe5b1415610e9f576035549050610ed2565b6000603a54118015610eb95750603a54610eb7612385565b105b15610ec75760009050610ed2565b610ecf611d73565b90505b90565b6000610eee60385460355461272f90919063ffffffff16565b905090565b6000610f296001610f1b610f05611fd6565b610f0d611a40565b61272f90919063ffffffff16565b610e1190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb390614493565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514611012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100990614313565b60405180910390fd5b61106d61101d611d4a565b611025610cc5565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b6000806110a6610cc5565b905060006110b2612291565b9050808211156110d8576110cf8183610dc190919063ffffffff16565b925050506110df565b6000925050505b90565b60006110fb603654603754610dc190919063ffffffff16565b905090565b603b60029054906101000a900460ff1615611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114790614533565b60405180910390fd5b6001603b60026101000a81548160ff0219169083151502179055506111868160200160208101906111819190613366565b61280b565b8060400160208101906111999190613366565b603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806060013560358190555080608001356036819055508060a0013560378190555060016038819055506001603b60036101000a81548160ff0219169083151502179055508060a001356039819055506002603b60006101000a81548160ff0219169083600281111561128857fe5b0217905550611296836128a9565b505050565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132290614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561139557600080fd5b505afa1580156113a9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113d291906134f8565b905060005b81518110156114d057603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061142a57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b8152600401611470929190614121565b602060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c29190613539565b5080806001019150506113d7565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156115ab57fe5b603b60009054906101000a900460ff1660028111156115c657fe5b14156115db576115d4612a27565b90506116a5565b60006039541180156115f557506039546115f3612385565b105b1561160357600090506116a5565b6001600281111561161057fe5b603b60009054906101000a900460ff16600281111561162b57fe5b14801561163a57506000603a54115b801561164e5750603a5461164c612385565b105b1561165c57600090506116a5565b600061168e603f54611680603c54611672611d73565b610dc190919063ffffffff16565b610dc190919063ffffffff16565b90506116a161169b610cc5565b82612ae1565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172f90614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906117df91906134f8565b905060005b81518110156118be57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061183757fe5b602002602001015160006040518363ffffffff1660e01b815260040161185e9291906140f8565b602060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b09190613539565b5080806001019150506117e4565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197390614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b600080611a4b612385565b90506036548111611a60576000915050611a79565b611a7560365482610dc190919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0990614593565b60405180910390fd5b6000611b1c61159d565b905060008111611b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b58906145f3565b60405180910390fd5b611b7681603c54610e1190919063ffffffff16565b603c81905550611beb603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611c539190614673565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890614593565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611d7e612385565b9050603654811015611d94576000915050611dce565b603754811115611da957603554915050611dce565b611dca611db4610ed5565b611dbc612514565b612afa90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5e90614593565b60405180910390fd5b60008111611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea190614413565b60405180910390fd5b80611eb361109b565b1015611ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eeb90614513565b60405180910390fd5b611f63603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611fcb9190614673565b60405180910390a250565b6000611ff4603854611fe66110e2565b61272f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614493565b60405180910390fd5b6001600281111561209457fe5b603b60009054906101000a900460ff1660028111156120af57fe5b146120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614553565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213c90614653565b60405180910390fd5b6000612163612152610e66565b603554610dc190919063ffffffff16565b9050600081116121a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219f906142d3565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061221e6121d5611d4a565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516122869190614673565b60405180910390a250565b60006122be603d546122b0603c54603554610dc190919063ffffffff16565b610dc190919063ffffffff16565b905090565b6122d58a8a8a8a8a8a8a8a8a8a612b6a565b6122de8b6128a9565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237090614493565b60405180910390fd5b612382816128a9565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461241d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161241490614593565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561248d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612484906143b3565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d816040516124fd91906140dd565b60405180910390a150565b603f5481565b60395481565b60006125316001612523610ef3565b610dc190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bb90614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262b90614293565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606127268484600085612ff4565b90509392505050565b6000808211612773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276a90614393565b60405180910390fd5b81838161277c57fe5b04905092915050565b6128068363a9059cbb60e01b84846040516024016127a4929190614121565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613109565b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291090614573565b60405180910390fd5b612922816131d0565b612961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612958906143f3565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b600080603954118015612a425750603954612a40612385565b105b15612a505760009050612ade565b60016002811115612a5d57fe5b603b60009054906101000a900460ff166002811115612a7857fe5b148015612a8757506000603a54115b8015612a9b5750603a54612a99612385565b105b15612aa95760009050612ade565b6000612ac7603c54612ab9611d73565b610dc190919063ffffffff16565b9050612ada612ad4610cc5565b82612ae1565b9150505b90565b6000818310612af05781612af2565b825b905092915050565b600080831415612b0d5760009050612b64565b6000828402905082848281612b1e57fe5b0414612b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5690614473565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff1615612bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb190614533565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c21906142f3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190614633565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0190614613565b60405180910390fd5b60008711612d4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4490614373565b60405180910390fd5b6000861415612d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d88906144b3565b60405180910390fd5b848610612dd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dca90614253565b60405180910390fd5b6001841015612e17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0e90614453565b60405180910390fd5b60006002811115612e2457fe5b816002811115612e3057fe5b1415612e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e6890614273565b60405180910390fd5b848310612eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eaa906145b3565b60405180910390fd5b848210612ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eec90614233565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612f198a61280b565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612fe357fe5b021790555050505050505050505050565b606082471015613039576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161303090614353565b60405180910390fd5b613042856131d0565b613081576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613078906144f3565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516130ab91906140c6565b60006040518083038185875af1925050503d80600081146130e8576040519150601f19603f3d011682016040523d82523d6000602084013e6130ed565b606091505b50915091506130fd8282866131e3565b92505050949350505050565b606061316b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166127179092919063ffffffff16565b90506000815111156131cb578080602001905181019061318b9190613539565b6131ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131c1906145d3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b606083156131f357829050613243565b6000835111156132065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323a91906141d1565b60405180910390fd5b9392505050565b6000813590506132598161486a565b92915050565b60008151905061326e8161486a565b92915050565b600082601f83011261328557600080fd5b8151613298613293826146bf565b61468e565b915081818352602084019350602081019050838560208402820111156132bd57600080fd5b60005b838110156132ed57816132d3888261325f565b8452602084019350602083019250506001810190506132c0565b5050505092915050565b60008151905061330681614881565b92915050565b60008135905061331b81614898565b92915050565b600060c0828403121561333357600080fd5b81905092915050565b60008135905061334b816148a8565b92915050565b600081519050613360816148a8565b92915050565b60006020828403121561337857600080fd5b60006133868482850161324a565b91505092915050565b6000602082840312156133a157600080fd5b60006133af8482850161325f565b91505092915050565b60008060008060008060008060008060006101608c8e0312156133da57600080fd5b60006133e88e828f0161324a565b9b505060206133f98e828f0161324a565b9a5050604061340a8e828f0161324a565b995050606061341b8e828f0161324a565b985050608061342c8e828f0161333c565b97505060a061343d8e828f0161333c565b96505060c061344e8e828f0161333c565b95505060e061345f8e828f0161333c565b9450506101006134718e828f0161333c565b9350506101206134838e828f0161333c565b9250506101406134958e828f0161330c565b9150509295989b509295989b9093969950565b600080600061010084860312156134be57600080fd5b60006134cc8682870161324a565b93505060206134dd8682870161324a565b92505060406134ee86828701613321565b9150509250925092565b60006020828403121561350a57600080fd5b600082015167ffffffffffffffff81111561352457600080fd5b61353084828501613274565b91505092915050565b60006020828403121561354b57600080fd5b6000613559848285016132f7565b91505092915050565b60006020828403121561357457600080fd5b60006135828482850161333c565b91505092915050565b60006020828403121561359d57600080fd5b60006135ab84828501613351565b91505092915050565b6135bd8161471d565b82525050565b6135cc8161472f565b82525050565b6135db8161473b565b82525050565b60006135ec826146eb565b6135f68185614701565b9350613606818560208601614810565b80840191505092915050565b61361b816147a4565b82525050565b61362a816147c8565b82525050565b613639816147ec565b82525050565b613648816147fe565b82525050565b6000613659826146f6565b613663818561470c565b9350613673818560208601614810565b61367c81614845565b840191505092915050565b600061369460088361470c565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b60006136d4601b8361470c565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b600061371460228361470c565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061377a60158361470c565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b60006137ba601e8361470c565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006137fa60268361470c565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613860601b8361470c565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006138a0601c8361470c565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006138e060148361470c565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613920601f8361470c565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613960601e8361470c565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006139a060268361470c565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a06601d8361470c565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b6000613a46601a8361470c565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b6000613a8660118361470c565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b6000613ac660138361470c565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b6000613b06601a8361470c565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b6000613b4660158361470c565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613b8660298361470c565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bec601f8361470c565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b6000613c2c60218361470c565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c9260208361470c565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613cd260168361470c565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613d1260158361470c565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613d52601d8361470c565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613d9260248361470c565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df860138361470c565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613e3860198361470c565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613e7860178361470c565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613eb860058361470c565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613ef8602a8361470c565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613f5e602a8361470c565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fc4601e8361470c565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b600061400460148361470c565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000614044601a8361470c565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000614084600f8361470c565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b6140c08161479a565b82525050565b60006140d282846135e1565b915081905092915050565b60006020820190506140f260008301846135b4565b92915050565b600060408201905061410d60008301856135b4565b61411a602083018461363f565b9392505050565b600060408201905061413660008301856135b4565b61414360208301846140b7565b9392505050565b600060208201905061415f60008301846135c3565b92915050565b600060208201905061417a60008301846135d2565b92915050565b60006020820190506141956000830184613612565b92915050565b60006020820190506141b06000830184613621565b92915050565b60006020820190506141cb6000830184613630565b92915050565b600060208201905081810360008301526141eb818461364e565b905092915050565b6000602082019050818103600083015261420c81613687565b9050919050565b6000602082019050818103600083015261422c816136c7565b9050919050565b6000602082019050818103600083015261424c81613707565b9050919050565b6000602082019050818103600083015261426c8161376d565b9050919050565b6000602082019050818103600083015261428c816137ad565b9050919050565b600060208201905081810360008301526142ac816137ed565b9050919050565b600060208201905081810360008301526142cc81613853565b9050919050565b600060208201905081810360008301526142ec81613893565b9050919050565b6000602082019050818103600083015261430c816138d3565b9050919050565b6000602082019050818103600083015261432c81613913565b9050919050565b6000602082019050818103600083015261434c81613953565b9050919050565b6000602082019050818103600083015261436c81613993565b9050919050565b6000602082019050818103600083015261438c816139f9565b9050919050565b600060208201905081810360008301526143ac81613a39565b9050919050565b600060208201905081810360008301526143cc81613a79565b9050919050565b600060208201905081810360008301526143ec81613ab9565b9050919050565b6000602082019050818103600083015261440c81613af9565b9050919050565b6000602082019050818103600083015261442c81613b39565b9050919050565b6000602082019050818103600083015261444c81613b79565b9050919050565b6000602082019050818103600083015261446c81613bdf565b9050919050565b6000602082019050818103600083015261448c81613c1f565b9050919050565b600060208201905081810360008301526144ac81613c85565b9050919050565b600060208201905081810360008301526144cc81613cc5565b9050919050565b600060208201905081810360008301526144ec81613d05565b9050919050565b6000602082019050818103600083015261450c81613d45565b9050919050565b6000602082019050818103600083015261452c81613d85565b9050919050565b6000602082019050818103600083015261454c81613deb565b9050919050565b6000602082019050818103600083015261456c81613e2b565b9050919050565b6000602082019050818103600083015261458c81613e6b565b9050919050565b600060208201905081810360008301526145ac81613eab565b9050919050565b600060208201905081810360008301526145cc81613eeb565b9050919050565b600060208201905081810360008301526145ec81613f51565b9050919050565b6000602082019050818103600083015261460c81613fb7565b9050919050565b6000602082019050818103600083015261462c81613ff7565b9050919050565b6000602082019050818103600083015261464c81614037565b9050919050565b6000602082019050818103600083015261466c81614077565b9050919050565b600060208201905061468860008301846140b7565b92915050565b6000604051905081810181811067ffffffffffffffff821117156146b5576146b4614843565b5b8060405250919050565b600067ffffffffffffffff8211156146da576146d9614843565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006147288261477a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061477582614856565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006147af826147b6565b9050919050565b60006147c18261477a565b9050919050565b60006147d3826147da565b9050919050565b60006147e58261477a565b9050919050565b60006147f782614767565b9050919050565b60006148098261479a565b9050919050565b60005b8381101561482e578082015181840152602081019050614813565b8381111561483d576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061486757614866614843565b5b50565b6148738161471d565b811461487e57600080fd5b50565b61488a8161472f565b811461489557600080fd5b50565b600381106148a557600080fd5b50565b6148b18161479a565b81146148bc57600080fd5b5056fea2646970667358221220e7181b2ba4d1c3bb9e57d12c063690ecc18fa07966017865e716378e6ce1068c64736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. This L2 variant includes a special initializer so that it can be created from a wallet's data received from L1. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1, so releasing surplus tokens might also only be possible by bridging tokens back to L1. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6797, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 6802, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 3244, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "51", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 3246, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "52", + "type": "t_address" + }, + { + "astId": 3248, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "53", + "type": "t_uint256" + }, + { + "astId": 3250, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "54", + "type": "t_uint256" + }, + { + "astId": 3252, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "55", + "type": "t_uint256" + }, + { + "astId": 3254, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 3256, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "57", + "type": "t_uint256" + }, + { + "astId": 3258, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "58", + "type": "t_uint256" + }, + { + "astId": 3260, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "59", + "type": "t_enum(Revocability)5096" + }, + { + "astId": 3262, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3264, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3266, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3268, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "60", + "type": "t_uint256" + }, + { + "astId": 3270, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "61", + "type": "t_uint256" + }, + { + "astId": 4692, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "62", + "type": "t_contract(IGraphTokenLockManager)5278" + }, + { + "astId": 4694, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "63", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)5278": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)5096": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json b/packages/token-distribution/deployments/arbitrum-goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json new file mode 100644 index 000000000..4eda754ae --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json @@ -0,0 +1,152 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMathUpgradeable {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/arbitrum/ITokenGateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2020, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\ninterface ITokenGateway {\n /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated\n // event OutboundTransferInitiated(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized\n // event InboundTransferFinalized(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n function outboundTransfer(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n function finalizeInboundTransfer(\n address _token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n\n /**\n * @notice Calculate the address used when bridging an ERC20 token\n * @dev the L1 and L2 address oracles may not always be in sync.\n * For example, a custom token may have been registered but not deployed or the contract self destructed.\n * @param l1ERC20 address of L1 token\n * @return L2 address of a bridged ERC20 token\n */\n function calculateL2TokenAddress(address l1ERC20) external view returns (address);\n}\n" + }, + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n OwnableInitializable._initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 internal _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSelector(\n GraphTokenLockWallet.initialize.selector,\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(\n string[] calldata _signatures,\n address[] calldata _targets\n ) external override onlyOwner {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n *\n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n OwnableInitializable._initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) internal {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe because we are using the max uint256 value\n token.approve(dstList[i], type(uint256).max);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe cause we're using 0 as the amount\n token.approve(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n require(msg.value == 0, \"ETH transfers not supported\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n\n /**\n * @notice Receive function that always reverts.\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\n */\n receive() external payable {\n revert(\"Bad call\");\n }\n}\n" + }, + "contracts/ICallhookReceiver.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\n\n/**\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\n * be allowlisted by the governor, but also implement this interface that contains\n * the function that will actually be called by the L2GraphTokenGateway.\n */\npragma solidity ^0.7.3;\n\ninterface ICallhookReceiver {\n /**\n * @notice Receive tokens with a callhook from the bridge\n * @param _from Token sender in L1\n * @param _amount Amount of tokens that were transferred\n * @param _data ABI-encoded callhook data\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/L1GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { AddressUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { MinimalProxyFactory } from \"./MinimalProxyFactory.sol\";\nimport { IGraphTokenLock } from \"./IGraphTokenLock.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { SafeMathUpgradeable } from \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @title L1GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from GraphTokenLockWallets\n * to a counterpart on L2. It is deployed on L1 and will send the GRT through\n * the L1GraphTokenGateway with a callhook to the L2GraphTokenLockManager, including\n * data to create a L2GraphTokenLockWallet on L2.\n *\n * Note that the L2GraphTokenLockWallet will not allow releasing any GRT until the end of\n * the vesting timeline, but will allow sending the GRT back to the L1 wallet.\n *\n * Beneficiaries for a GraphTokenLockWallet can perform the depositToL2Locked call\n * as many times as they want, and the GRT will be sent to the same L2GraphTokenLockWallet.\n *\n * Since all retryable tickets to send transactions to L2 require ETH for gas, this\n * contract also allows users to deposit ETH to be used for gas on L2, both for\n * the depositToL2Locked calls and for the transfer tools in the Staking contract for\n * The Graph.\n *\n * See GIP-0046 for more details: https://forum.thegraph.com/t/4023\n */\ncontract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, MinimalProxyFactory {\n using SafeMathUpgradeable for uint256;\n\n /// Address of the L1 GRT token contract\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses\n address public immutable l2Implementation;\n /// Address of the L1GraphTokenGateway contract\n ITokenGateway public immutable l1Gateway;\n /// Address of the Staking contract, used to pull ETH for L2 ticket gas\n address payable public immutable staking;\n /// L2 lock manager for each L1 lock manager.\n /// L1 GraphTokenLockManager => L2GraphTokenLockManager\n mapping(address => address) public l2LockManager;\n /// L2 wallet owner for each L1 wallet owner.\n /// L1 wallet owner => L2 wallet owner\n mapping(address => address) public l2WalletOwner;\n /// L2 wallet address for each L1 wallet address.\n /// L1 wallet => L2 wallet\n mapping(address => address) public l2WalletAddress;\n /// ETH balance from each token lock, used to pay for L2 gas:\n /// L1 wallet address => ETH balance\n mapping(address => uint256) public tokenLockETHBalances;\n /// L2 beneficiary corresponding to each L1 wallet address.\n /// L1 wallet => L2 beneficiary\n mapping(address => address) public l2Beneficiary;\n /// Indicates whether an L2 wallet address for a wallet\n /// has been set manually, in which case it can't call depositToL2Locked.\n /// L1 wallet => bool\n mapping(address => bool) public l2WalletAddressSetManually;\n\n /// @dev Emitted when the L2 lock manager for an L1 lock manager is set\n event L2LockManagerSet(address indexed l1LockManager, address indexed l2LockManager);\n /// @dev Emitted when the L2 wallet owner for an L1 wallet owner is set\n event L2WalletOwnerSet(address indexed l1WalletOwner, address indexed l2WalletOwner);\n /// @dev Emitted when GRT is sent to L2 from a token lock\n event LockedFundsSentToL2(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l1LockManager,\n address l2LockManager,\n uint256 amount\n );\n /// @dev Emitted when an L2 wallet address is set for an L1 wallet\n event L2WalletAddressSet(address indexed l1Wallet, address indexed l2Wallet);\n /// @dev Emitted when ETH is deposited to a token lock's account\n event ETHDeposited(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when ETH is withdrawn from a token lock's account\n event ETHWithdrawn(address indexed tokenLock, address indexed destination, uint256 amount);\n /// @dev Emitted when ETH is pulled from a token lock's account by Staking or this tool to pay for an L2 ticket\n event ETHPulled(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when the L2 beneficiary for a partially vested L1 lock is set\n event L2BeneficiarySet(address indexed l1Wallet, address indexed l2Beneficiary);\n\n /**\n * @notice Construct a new L1GraphTokenLockTransferTool contract\n * @dev The deployer of the contract will become its owner.\n * Note this contract is meant to be deployed behind a transparent proxy,\n * so this will run at the implementation's storage context; it will set\n * immutable variables and make the implementation be owned by the deployer.\n * @param _graphToken Address of the L1 GRT token contract\n * @param _l2Implementation Address of the L2GraphTokenLockWallet implementation in L2\n * @param _l1Gateway Address of the L1GraphTokenGateway contract\n * @param _staking Address of the Staking contract\n */\n constructor(\n IERC20 _graphToken,\n address _l2Implementation,\n ITokenGateway _l1Gateway,\n address payable _staking\n ) initializer {\n OwnableInitializable._initialize(msg.sender);\n graphToken = _graphToken;\n l2Implementation = _l2Implementation;\n l1Gateway = _l1Gateway;\n staking = _staking;\n }\n\n /**\n * @notice Initialize the L1GraphTokenLockTransferTool contract\n * @dev This function will run in the proxy's storage context, so it will\n * set the owner of the proxy contract which can be different from the implementation owner.\n * @param _owner Address of the owner of the L1GraphTokenLockTransferTool contract\n */\n function initialize(address _owner) external initializer {\n OwnableInitializable._initialize(_owner);\n }\n\n /**\n * @notice Set the L2 lock manager that corresponds to an L1 lock manager\n * @param _l1LockManager Address of the L1 lock manager\n * @param _l2LockManager Address of the L2 lock manager (in L2)\n */\n function setL2LockManager(address _l1LockManager, address _l2LockManager) external onlyOwner {\n l2LockManager[_l1LockManager] = _l2LockManager;\n emit L2LockManagerSet(_l1LockManager, _l2LockManager);\n }\n\n /**\n * @notice Set the L2 wallet owner that corresponds to an L1 wallet owner\n * @param _l1WalletOwner Address of the L1 wallet owner\n * @param _l2WalletOwner Address of the L2 wallet owner (in L2)\n */\n function setL2WalletOwner(address _l1WalletOwner, address _l2WalletOwner) external onlyOwner {\n l2WalletOwner[_l1WalletOwner] = _l2WalletOwner;\n emit L2WalletOwnerSet(_l1WalletOwner, _l2WalletOwner);\n }\n\n /**\n * @notice Deposit ETH on a token lock's account, to be used for L2 retryable ticket gas.\n * This function can be called by anyone, but the ETH will be credited to the token lock.\n * DO NOT try to call this through the token lock, as locks do not forward ETH value (and the\n * function call should not be allowlisted).\n * @param _tokenLock Address of the L1 GraphTokenLockWallet that will own the ETH\n */\n function depositETH(address _tokenLock) external payable {\n tokenLockETHBalances[_tokenLock] = tokenLockETHBalances[_tokenLock].add(msg.value);\n emit ETHDeposited(_tokenLock, msg.value);\n }\n\n /**\n * @notice Withdraw ETH from a token lock's account.\n * This function must be called from the token lock contract, but the destination\n * _must_ be a different address, as any ETH sent to the token lock would otherwise be\n * lost.\n * @param _destination Address to send the ETH\n * @param _amount Amount of ETH to send\n */\n function withdrawETH(address _destination, uint256 _amount) external {\n require(_amount > 0, \"INVALID_AMOUNT\");\n // We can't send eth to a token lock or it will be stuck\n require(msg.sender != _destination, \"INVALID_DESTINATION\");\n require(tokenLockETHBalances[msg.sender] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[msg.sender] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = payable(_destination).call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHWithdrawn(msg.sender, _destination, _amount);\n }\n\n /**\n * @notice Pull ETH from a token lock's account, to be used for L2 retryable ticket gas.\n * This can only be called by the Staking contract.\n * @param _tokenLock GraphTokenLockWallet that owns the ETH that will be debited\n * @param _amount Amount of ETH to pull\n */\n function pullETH(address _tokenLock, uint256 _amount) external {\n require(msg.sender == staking, \"ONLY_STAKING\");\n require(tokenLockETHBalances[_tokenLock] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[_tokenLock] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = staking.call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHPulled(_tokenLock, _amount);\n }\n\n /**\n * @notice Deposit GRT to L2, from a token lock in L1 to a token lock in L2.\n * If the token lock in L2 does not exist, it will be created when the message is received\n * by the L2GraphTokenLockManager.\n * Before calling this (which must be done through the token lock wallet), make sure\n * there is enough ETH in the token lock's account to cover the L2 retryable ticket gas.\n * Note that L2 submission fee and gas refunds will be lost.\n * You can add ETH to the token lock's account by calling depositETH().\n * Note that after calling this, you will NOT be able to use setL2WalletAddressManually() to\n * set an L2 wallet address, as the L2 wallet address will be set automatically when the\n * message is received by the L2GraphTokenLockManager.\n * @dev The gas parameters for L2 can be estimated using the Arbitrum SDK.\n * @param _amount Amount of GRT to deposit\n * @param _l2Beneficiary Address of the beneficiary for the token lock in L2. Must be the same for subsequent calls of this function, and not an L1 contract.\n * @param _maxGas Maximum gas to use for the L2 retryable ticket\n * @param _gasPriceBid Gas price to use for the L2 retryable ticket\n * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket\n */\n function depositToL2Locked(\n uint256 _amount,\n address _l2Beneficiary,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n uint256 _maxSubmissionCost\n ) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n require(wallet.revocable() != IGraphTokenLock.Revocability.Enabled, \"REVOCABLE\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n if (l2Beneficiary[msg.sender] == address(0)) {\n require(_l2Beneficiary != address(0), \"INVALID_BENEFICIARY_ZERO\");\n require(!AddressUpgradeable.isContract(_l2Beneficiary), \"INVALID_BENEFICIARY_CONTRACT\");\n l2Beneficiary[msg.sender] = _l2Beneficiary;\n emit L2BeneficiarySet(msg.sender, _l2Beneficiary);\n } else {\n require(l2Beneficiary[msg.sender] == _l2Beneficiary, \"INVALID_BENEFICIARY\");\n }\n\n uint256 expectedEth = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(tokenLockETHBalances[msg.sender] >= expectedEth, \"INSUFFICIENT_ETH_BALANCE\");\n tokenLockETHBalances[msg.sender] -= expectedEth;\n\n bytes memory encodedData;\n {\n address l2Owner = l2WalletOwner[wallet.owner()];\n require(l2Owner != address(0), \"L2_OWNER_NOT_SET\");\n // Extract all the storage variables from the GraphTokenLockWallet\n L2GraphTokenLockManager.TransferredWalletData memory data = L2GraphTokenLockManager.TransferredWalletData({\n l1Address: msg.sender,\n owner: l2Owner,\n beneficiary: l2Beneficiary[msg.sender],\n managedAmount: wallet.managedAmount(),\n startTime: wallet.startTime(),\n endTime: wallet.endTime()\n });\n encodedData = abi.encode(data);\n }\n\n if (l2WalletAddress[msg.sender] == address(0)) {\n require(wallet.endTime() >= block.timestamp, \"FULLY_VESTED_USE_MANUAL_ADDRESS\");\n address newAddress = getDeploymentAddress(keccak256(encodedData), l2Implementation, l2Manager);\n l2WalletAddress[msg.sender] = newAddress;\n emit L2WalletAddressSet(msg.sender, newAddress);\n } else {\n require(!l2WalletAddressSetManually[msg.sender], \"CANT_DEPOSIT_TO_MANUAL_ADDRESS\");\n }\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n\n // Send the tokens with a message through the L1GraphTokenGateway to the L2GraphTokenLockManager\n graphToken.approve(address(l1Gateway), _amount);\n {\n bytes memory transferData = abi.encode(_maxSubmissionCost, encodedData);\n l1Gateway.outboundTransfer{ value: expectedEth }(\n address(graphToken),\n l2Manager,\n _amount,\n _maxGas,\n _gasPriceBid,\n transferData\n );\n }\n emit ETHPulled(msg.sender, expectedEth);\n emit LockedFundsSentToL2(msg.sender, l2WalletAddress[msg.sender], l1Manager, l2Manager, _amount);\n }\n\n /**\n * @notice Manually set the L2 wallet address for a token lock in L1.\n * This will only work for token locks that have not been initialized in L2 yet, and\n * that are fully vested (endTime < current timestamp).\n * This address can then be used to send stake or delegation to L2 on the Staking contract.\n * After calling this, the vesting lock will NOT be allowed to use depositToL2Locked\n * to send GRT to L2, the beneficiary must withdraw the tokens and bridge them manually.\n * @param _l2Wallet Address of the L2 wallet\n */\n function setL2WalletAddressManually(address _l2Wallet) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n\n // Check that the wallet is fully vested\n require(wallet.endTime() < block.timestamp, \"NOT_FULLY_VESTED\");\n\n // Check that the wallet has not set an L2 wallet yet\n require(l2WalletAddress[msg.sender] == address(0), \"L2_WALLET_ALREADY_SET\");\n\n // Check that the L2 address is not zero\n require(_l2Wallet != address(0), \"ZERO_ADDRESS\");\n // Set the L2 wallet address\n l2WalletAddress[msg.sender] = _l2Wallet;\n l2WalletAddressSetManually[msg.sender] = true;\n emit L2WalletAddressSet(msg.sender, _l2Wallet);\n }\n}\n" + }, + "contracts/L2GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { ICallhookReceiver } from \"./ICallhookReceiver.sol\";\nimport { GraphTokenLockManager } from \"./GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\n\n/**\n * @title L2GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\n * the L2GraphTokenLockTransferTool contract.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\n using SafeERC20 for IERC20;\n\n /// @dev Struct to hold the data of a transferred wallet; this is\n /// the data that must be encoded in L1 to send a wallet to L2.\n struct TransferredWalletData {\n address l1Address;\n address owner;\n address beneficiary;\n uint256 managedAmount;\n uint256 startTime;\n uint256 endTime;\n }\n\n /// Address of the L2GraphTokenGateway\n address public immutable l2Gateway;\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\n address public immutable l1TransferTool;\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\n /// L1 address => L2 address\n mapping(address => address) public l1WalletToL2Wallet;\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\n /// L2 address => L1 address\n mapping(address => address) public l2WalletToL1Wallet;\n\n /// @dev Event emitted when a wallet is received and created from L1\n event TokenLockCreatedFromL1(\n address indexed contractAddress,\n bytes32 initHash,\n address indexed beneficiary,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n address indexed l1Address\n );\n\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\n /// had already been received or not)\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\n\n /**\n * @dev Checks that the sender is the L2GraphTokenGateway.\n */\n modifier onlyL2Gateway() {\n require(msg.sender == l2Gateway, \"ONLY_GATEWAY\");\n _;\n }\n\n /**\n * @notice Constructor for the L2GraphTokenLockManager contract.\n * @param _graphToken Address of the L2 GRT token contract\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\n */\n constructor(\n IERC20 _graphToken,\n address _masterCopy,\n address _l2Gateway,\n address _l1TransferTool\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\n l2Gateway = _l2Gateway;\n l1TransferTool = _l1TransferTool;\n }\n\n /**\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\n * the existing wallet if it does.\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\n * @param _amount Amount of tokens received\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\n require(_from == l1TransferTool, \"ONLY_TRANSFER_TOOL\");\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\n\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\n // If the wallet was already received, just send the tokens to the L2 address\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\n } else {\n // Create contract using a minimal proxy and call initializer\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _amount);\n\n emit TokenLockCreatedFromL1(\n contractAddress,\n initHash,\n walletData.beneficiary,\n walletData.managedAmount,\n walletData.startTime,\n walletData.endTime,\n walletData.l1Address\n );\n }\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\n }\n\n /**\n * @dev Deploy a token lock wallet with data received from L1\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\n * @param _walletData Data of the wallet to be created\n * @return Hash of the initialization calldata\n * @return Address of the created contract\n */\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\n bytes memory initializer = _encodeInitializer(_walletData);\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\n return (keccak256(initializer), contractAddress);\n }\n\n /**\n * @dev Encode the initializer for the token lock wallet received from L1\n * @param _walletData Data of the wallet to be created\n * @return Encoded initializer calldata, including the function signature\n */\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\n return\n abi.encodeWithSelector(\n L2GraphTokenLockWallet.initializeFromL1.selector,\n address(this),\n address(_token),\n _walletData\n );\n }\n}\n" + }, + "contracts/L2GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\n\n/**\n * @title L2GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from L2 token lock wallets\n * back to their L1 counterparts.\n */\ncontract L2GraphTokenLockTransferTool {\n /// Address of the L2 GRT token\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenGateway\n ITokenGateway public immutable l2Gateway;\n /// Address of the L1 GRT token (in L1, no aliasing)\n address public immutable l1GraphToken;\n\n /// @dev Emitted when GRT is sent to L1 from a token lock\n event LockedFundsSentToL1(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l2LockManager,\n uint256 amount\n );\n\n /**\n * @notice Constructor for the L2GraphTokenLockTransferTool contract\n * @dev Note the L2GraphTokenLockTransferTool can be deployed behind a proxy,\n * and the constructor for the implementation will only set some immutable\n * variables.\n * @param _graphToken Address of the L2 GRT token\n * @param _l2Gateway Address of the L2GraphTokenGateway\n * @param _l1GraphToken Address of the L1 GRT token (in L1, no aliasing)\n */\n constructor(IERC20 _graphToken, ITokenGateway _l2Gateway, address _l1GraphToken) {\n graphToken = _graphToken;\n l2Gateway = _l2Gateway;\n l1GraphToken = _l1GraphToken;\n }\n\n /**\n * @notice Withdraw GRT from an L2 token lock wallet to its L1 counterpart.\n * This function must be called from an L2GraphTokenLockWallet contract.\n * The GRT will be sent to L1 and must be claimed using the Arbitrum Outbox on L1\n * after the standard Arbitrum withdrawal period (7 days).\n * @param _amount Amount of GRT to withdraw\n */\n function withdrawToL1Locked(uint256 _amount) external {\n L2GraphTokenLockWallet wallet = L2GraphTokenLockWallet(msg.sender);\n L2GraphTokenLockManager manager = L2GraphTokenLockManager(address(wallet.manager()));\n require(address(manager) != address(0), \"INVALID_SENDER\");\n address l1Wallet = manager.l2WalletToL1Wallet(msg.sender);\n require(l1Wallet != address(0), \"NOT_L1_WALLET\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n graphToken.approve(address(l2Gateway), _amount);\n\n // Send the tokens through the L2GraphTokenGateway to the L1 wallet counterpart\n l2Gateway.outboundTransfer(l1GraphToken, l1Wallet, _amount, 0, 0, \"\");\n emit LockedFundsSentToL1(l1Wallet, msg.sender, address(manager), _amount);\n }\n}\n" + }, + "contracts/L2GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\n\n/**\n * @title L2GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * This L2 variant includes a special initializer so that it can be created from\n * a wallet's data received from L1. These transferred wallets will not allow releasing\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\n *\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\n // Initializer when created from a message from L1\n function initializeFromL1(\n address _manager,\n address _token,\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\n ) external {\n require(!isInitialized, \"Already initialized\");\n isInitialized = true;\n\n OwnableInitializable._initialize(_walletData.owner);\n beneficiary = _walletData.beneficiary;\n token = IERC20(_token);\n\n managedAmount = _walletData.managedAmount;\n\n startTime = _walletData.startTime;\n endTime = _walletData.endTime;\n periods = 1;\n isAccepted = true;\n\n // Optionals\n releaseStartTime = _walletData.endTime;\n revocable = Revocability.Disabled;\n\n _setManager(_manager);\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { Create2 } from \"@openzeppelin/contracts/utils/Create2.sol\";\n\n/**\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n * Based on https://eips.ethereum.org/EIPS/eip-1167\n */\ncontract MinimalProxyFactory {\n /// @dev Emitted when a new proxy is created\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _deployer Address of the deployer that creates the contract\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation,\n address _deployer\n ) public pure returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\n }\n\n /**\n * @dev Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @dev Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n /// @dev Owner of the contract, can be retrieved with the public owner() function\n address private _owner;\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\n /// to allow adding variables here without breaking the proxy storage layout\n uint256[50] private __gap;\n\n /// @dev Emitted when ownership of the contract is transferred\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function _initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/tests/arbitrum/AddressAliasHelper.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/84e64dee6ee82adbf8ec34fd4b86c207a61d9007/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n l2Address = address(uint160(l1Address) + offset);\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n l1Address = address(uint160(l2Address) - offset);\n }\n}\n" + }, + "contracts/tests/arbitrum/IBridge.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IBridge {\n event MessageDelivered(\n uint256 indexed messageIndex,\n bytes32 indexed beforeInboxAcc,\n address inbox,\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n );\n\n event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);\n\n event InboxToggle(address indexed inbox, bool enabled);\n\n event OutboxToggle(address indexed outbox, bool enabled);\n\n function deliverMessageToInbox(\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n ) external payable returns (uint256);\n\n function executeCall(\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (bool success, bytes memory returnData);\n\n // These are only callable by the admin\n function setInbox(address inbox, bool enabled) external;\n\n function setOutbox(address inbox, bool enabled) external;\n\n // View functions\n\n function activeOutbox() external view returns (address);\n\n function allowedInboxes(address inbox) external view returns (bool);\n\n function allowedOutboxes(address outbox) external view returns (bool);\n\n function inboxAccs(uint256 index) external view returns (bytes32);\n\n function messageCount() external view returns (uint256);\n}\n" + }, + "contracts/tests/arbitrum/IInbox.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nimport \"./IBridge.sol\";\nimport \"./IMessageProvider.sol\";\n\ninterface IInbox is IMessageProvider {\n function sendL2Message(bytes calldata messageData) external returns (uint256);\n\n function sendUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendL1FundedUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function sendL1FundedContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function createRetryableTicket(\n address destAddr,\n uint256 arbTxCallValue,\n uint256 maxSubmissionCost,\n address submissionRefundAddress,\n address valueRefundAddress,\n uint256 maxGas,\n uint256 gasPriceBid,\n bytes calldata data\n ) external payable returns (uint256);\n\n function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);\n\n function bridge() external view returns (IBridge);\n\n function pauseCreateRetryables() external;\n\n function unpauseCreateRetryables() external;\n\n function startRewriteAddress() external;\n\n function stopRewriteAddress() external;\n}\n" + }, + "contracts/tests/arbitrum/IMessageProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IMessageProvider {\n event InboxMessageDelivered(uint256 indexed messageNum, bytes data);\n\n event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);\n}\n" + }, + "contracts/tests/BridgeMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IBridge.sol\";\n\n/**\n * @title Arbitrum Bridge mock contract\n * @dev This contract implements Arbitrum's IBridge interface for testing purposes\n */\ncontract BridgeMock is IBridge {\n /// Address of the (mock) Arbitrum Inbox\n address public inbox;\n /// Address of the (mock) Arbitrum Outbox\n address public outbox;\n /// Index of the next message on the inbox messages array\n uint256 public messageIndex;\n /// Inbox messages array\n bytes32[] public override inboxAccs;\n\n /**\n * @notice Deliver a message to the inbox. The encoded message will be\n * added to the inbox array, and messageIndex will be incremented.\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the message data\n * @return The next index for the inbox array\n */\n function deliverMessageToInbox(\n uint8 _kind,\n address _sender,\n bytes32 _messageDataHash\n ) external payable override returns (uint256) {\n messageIndex = messageIndex + 1;\n inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash)));\n emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash);\n return messageIndex;\n }\n\n /**\n * @notice Executes an L1 function call incoing from L2. This can only be called\n * by the Outbox.\n * @param _destAddr Contract to call\n * @param _amount ETH value to send\n * @param _data Calldata for the function call\n * @return True if the call was successful, false otherwise\n * @return Return data from the call\n */\n function executeCall(\n address _destAddr,\n uint256 _amount,\n bytes calldata _data\n ) external override returns (bool, bytes memory) {\n require(outbox == msg.sender, \"NOT_FROM_OUTBOX\");\n bool success;\n bytes memory returnData;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, returnData) = _destAddr.call{ value: _amount }(_data);\n emit BridgeCallTriggered(msg.sender, _destAddr, _amount, _data);\n return (success, returnData);\n }\n\n /**\n * @notice Set the address of the inbox. Anyone can call this, because it's a mock.\n * @param _inbox Address of the inbox\n * @param _enabled Enable the inbox (ignored)\n */\n function setInbox(address _inbox, bool _enabled) external override {\n inbox = _inbox;\n emit InboxToggle(inbox, _enabled);\n }\n\n /**\n * @notice Set the address of the outbox. Anyone can call this, because it's a mock.\n * @param _outbox Address of the outbox\n * @param _enabled Enable the outbox (ignored)\n */\n function setOutbox(address _outbox, bool _enabled) external override {\n outbox = _outbox;\n emit OutboxToggle(outbox, _enabled);\n }\n\n // View functions\n\n /**\n * @notice Getter for the active outbox (in this case there's only one)\n */\n function activeOutbox() external view override returns (address) {\n return outbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed inbox (in this case there's only one)\n * @param _inbox Address to check\n * @return True if the address is the allowed inbox, false otherwise\n */\n function allowedInboxes(address _inbox) external view override returns (bool) {\n return _inbox == inbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed outbox (in this case there's only one)\n * @param _outbox Address to check\n * @return True if the address is the allowed outbox, false otherwise\n */\n function allowedOutboxes(address _outbox) external view override returns (bool) {\n return _outbox == outbox;\n }\n\n /**\n * @notice Getter for the count of messages in the inboxAccs\n * @return Number of messages in inboxAccs\n */\n function messageCount() external view override returns (uint256) {\n return inboxAccs.length;\n }\n}\n" + }, + "contracts/tests/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock contract.\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @notice Contract Constructor.\n * @param _initialSupply Initial supply\n * @param _mintTo Address to whitch to mint the initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n\n /**\n * @notice Mint tokens to an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _to Address to mint tokens to\n * @param _amount Amount of tokens to mint\n */\n function bridgeMint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n\n /**\n * @notice Burn tokens from an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _from Address to burn tokens from\n * @param _amount Amount of tokens to burn\n */\n function bridgeBurn(address _from, uint256 _amount) external {\n _burn(_from, _amount);\n }\n}\n" + }, + "contracts/tests/InboxMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IInbox.sol\";\nimport \"./arbitrum/AddressAliasHelper.sol\";\n\n/**\n * @title Arbitrum Inbox mock contract\n * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes\n */\ncontract InboxMock is IInbox {\n /// @dev Type indicator for a standard L2 message\n uint8 internal constant L2_MSG = 3;\n /// @dev Type indicator for a retryable ticket message\n // solhint-disable-next-line const-name-snakecase\n uint8 internal constant L1MessageType_submitRetryableTx = 9;\n /// Address of the Bridge (mock) contract\n IBridge public override bridge;\n\n /**\n * @notice Send a message to L2 (by delivering it to the Bridge)\n * @param _messageData Encoded data to send in the message\n * @return Message number returned by the inbox\n */\n function sendL2Message(bytes calldata _messageData) external override returns (uint256) {\n uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @notice Set the address of the (mock) bridge\n * @param _bridge Address of the bridge\n */\n function setBridge(address _bridge) external {\n bridge = IBridge(_bridge);\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendContractTransaction(\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedContractTransaction(\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Creates a retryable ticket for an L2 transaction\n * @param _destAddr Address of the contract to call in L2\n * @param _arbTxCallValue Callvalue to use in the L2 transaction\n * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei\n * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost\n * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled\n * @param _maxGas Max gas for the L2 transcation\n * @param _gasPriceBid Gas price bid on L2\n * @param _data Encoded calldata for the L2 transaction (including function selector)\n * @return Message number returned by the bridge\n */\n function createRetryableTicket(\n address _destAddr,\n uint256 _arbTxCallValue,\n uint256 _maxSubmissionCost,\n address _submissionRefundAddress,\n address _valueRefundAddress,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable override returns (uint256) {\n _submissionRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_submissionRefundAddress);\n _valueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_valueRefundAddress);\n return\n _deliverMessage(\n L1MessageType_submitRetryableTx,\n msg.sender,\n abi.encodePacked(\n uint256(uint160(bytes20(_destAddr))),\n _arbTxCallValue,\n msg.value,\n _maxSubmissionCost,\n uint256(uint160(bytes20(_submissionRefundAddress))),\n uint256(uint160(bytes20(_valueRefundAddress))),\n _maxGas,\n _gasPriceBid,\n _data.length,\n _data\n )\n );\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function depositEth(uint256) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function pauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function unpauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function startRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function stopRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageData Encoded message data\n * @return Message number returned by the bridge\n */\n function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) {\n uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the encoded message data\n * @return Message number returned by the bridge\n */\n function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) {\n return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash);\n }\n}\n" + }, + "contracts/tests/L1TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\n\n/**\n * @title L1 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L1TokenGatewayMock is Ownable {\n using SafeMath for uint256;\n /// Next sequence number to return when outboundTransfer is called\n uint256 public nextSeqNum;\n\n /// @dev Emitted when a (fake) retryable ticket is created\n event FakeTxToL2(\n address from,\n uint256 value,\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 maxSubmissionCost,\n bytes outboundCalldata\n );\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2\n event DepositInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L1 Token Gateway Contract Constructor.\n */\n constructor() {}\n\n /**\n * @notice Creates and sends a fake retryable ticket to transfer GRT to L2.\n * This mock will actually just emit an event with parameters equivalent to what the real L1GraphTokenGateway\n * would send to L2.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _maxGas Gas limit for L2 execution of the ticket\n * @param _gasPriceBid Price per gas on L2\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return Sequence number of the retryable ticket created by Inbox (always )\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 seqNum = nextSeqNum;\n nextSeqNum += 1;\n {\n uint256 maxSubmissionCost;\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, maxSubmissionCost, extraData) = _parseOutboundData(_data);\n require(maxSubmissionCost > 0, \"NO_SUBMISSION_COST\");\n\n {\n // makes sure only sufficient ETH is supplied as required for successful redemption on L2\n // if a user does not desire immediate redemption they should provide\n // a msg.value of AT LEAST maxSubmissionCost\n uint256 expectedEth = maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(msg.value >= expectedEth, \"WRONG_ETH_VALUE\");\n }\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // transfer tokens to escrow\n IERC20(_l1Token).transferFrom(from, address(this), _amount);\n\n emit FakeTxToL2(from, msg.value, _maxGas, _gasPriceBid, maxSubmissionCost, outboundCalldata);\n }\n }\n emit DepositInitiated(_l1Token, from, _to, seqNum, _amount);\n\n return abi.encode(seqNum);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L2\n * Actually does nothing, just keeping it here as its useful to define the expected\n * calldata for the outgoing transfer in tests.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recepient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {}\n\n /**\n * @notice Creates calldata required to create a retryable ticket\n * @dev encodes the target function with its params which\n * will be called on L2 when the retryable ticket is redeemed\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L1 from which we're transferring tokens\n * @param _to Address on L2 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L2 transaction, which must be empty unless the caller is whitelisted\n * @return Encoded calldata (including function selector) for the L2 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n bytes memory emptyBytes;\n\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(emptyBytes, _data)\n );\n }\n\n /**\n * @notice Decodes calldata required for transfer of tokens to L2\n * @dev Data must include maxSubmissionCost, extraData can be left empty. When the router\n * sends an outbound message, data also contains the from address, but this mock\n * doesn't consider this case\n * @param _data Encoded callhook data containing maxSubmissionCost and extraData\n * @return Sender of the tx\n * @return Max ether value used to submit the retryable ticket\n * @return Additional data sent to L2\n */\n function _parseOutboundData(bytes memory _data) private view returns (address, uint256, bytes memory) {\n address from;\n uint256 maxSubmissionCost;\n bytes memory extraData;\n from = msg.sender;\n // User-encoded data contains the max retryable ticket submission cost\n // and additional L2 calldata\n (maxSubmissionCost, extraData) = abi.decode(_data, (uint256, bytes));\n return (from, maxSubmissionCost, extraData);\n }\n}\n" + }, + "contracts/tests/L2TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\nimport { GraphTokenMock } from \"./GraphTokenMock.sol\";\nimport { ICallhookReceiver } from \"../ICallhookReceiver.sol\";\n\n/**\n * @title L2 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L2TokenGatewayMock is Ownable {\n /// Address of the L1 GRT contract\n address public immutable l1Token;\n /// Address of the L2 GRT contract\n address public immutable l2Token;\n /// Next ID to return when sending an outboundTransfer\n uint256 public nextId;\n\n /// @dev Emitted when a (fake) transaction to L1 is created\n event FakeTxToL1(address from, bytes outboundCalldata);\n /// @dev Emitted when a (fake) retryable ticket is received from L1\n event DepositFinalized(address token, address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are withdrawn to L1 from L2\n event WithdrawalInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L2 Token Gateway Contract Constructor.\n * @param _l1Token Address of the L1 GRT contract\n * @param _l2Token Address of the L2 GRT contract\n */\n constructor(address _l1Token, address _l2Token) {\n l1Token = _l1Token;\n l2Token = _l2Token;\n }\n\n /**\n * @notice Creates and sends a (fake) transfer of GRT to L1.\n * This mock will actually just emit an event with parameters equivalent to what the real L2GraphTokenGateway\n * would send to L1.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return ID of the L2-L1 message (incrementing on every call)\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_l1Token == l1Token, \"INVALID_L1_TOKEN\");\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 id = nextId;\n nextId += 1;\n {\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, extraData) = _parseOutboundData(_data);\n\n require(msg.value == 0, \"!value\");\n require(extraData.length == 0, \"!extraData\");\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // burn tokens from the sender, they will be released from escrow in L1\n GraphTokenMock(l2Token).bridgeBurn(from, _amount);\n\n emit FakeTxToL1(from, outboundCalldata);\n }\n }\n emit WithdrawalInitiated(_l1Token, from, _to, id, _amount);\n\n return abi.encode(id);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L1\n * Implements calling callhooks if data is non-empty.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recipient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata, will trigger an onTokenTransfer call if non-empty\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {\n require(_l1Token == l1Token, \"TOKEN_NOT_GRT\");\n require(msg.value == 0, \"INVALID_NONZERO_VALUE\");\n\n GraphTokenMock(l2Token).bridgeMint(_to, _amount);\n\n if (_data.length > 0) {\n ICallhookReceiver(_to).onTokenTransfer(_from, _amount, _data);\n }\n\n emit DepositFinalized(_l1Token, _from, _to, _amount);\n }\n\n /**\n * @notice Calculate the L2 address of a bridged token\n * @dev In our case, this would only work for GRT.\n * @param l1ERC20 address of L1 GRT contract\n * @return L2 address of the bridged GRT token\n */\n function calculateL2TokenAddress(address l1ERC20) public view returns (address) {\n if (l1ERC20 != l1Token) {\n return address(0);\n }\n return l2Token;\n }\n\n /**\n * @notice Creates calldata required to create a tx to L1\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L2 from which we're transferring tokens\n * @param _to Address on L1 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L1 transaction, which must be empty\n * @return Encoded calldata (including function selector) for the L1 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(0, _data)\n );\n }\n\n /**\n * @dev Decodes calldata required for transfer of tokens to L1.\n * extraData can be left empty\n * @param _data Encoded callhook data\n * @return Sender of the tx\n * @return Any other data sent to L1\n */\n function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {\n address from;\n bytes memory extraData;\n // The mock doesn't take messages from the Router\n from = msg.sender;\n extraData = _data;\n return (from, extraData);\n }\n}\n" + }, + "contracts/tests/Stakes.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(\n Stakes.Indexer memory stake,\n uint256 _delegatedCapacity\n ) internal pure returns (uint256) {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "contracts/tests/StakingMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n receive() external payable {}\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/tests/WalletMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title WalletMock: a mock wallet contract for testing purposes\n * @dev For testing only, DO NOT USE IN PRODUCTION.\n * This is used to test L1-L2 transfer tools and to create scenarios\n * where an invalid wallet calls the transfer tool, e.g. a wallet that has an invalid\n * manager, or a wallet that has not been initialized.\n */\ncontract WalletMock {\n /// Target contract for the fallback function (usually a transfer tool contract)\n address public immutable target;\n /// Address of the GRT (mock) token\n address public immutable token;\n /// Address of the wallet's manager\n address public immutable manager;\n /// Whether the wallet has been initialized\n bool public immutable isInitialized;\n /// Whether the beneficiary has accepted the lock\n bool public immutable isAccepted;\n\n /**\n * @notice WalletMock constructor\n * @dev This constructor sets all the state variables so that\n * specific test scenarios can be created just by deploying this contract.\n * @param _target Target contract for the fallback function\n * @param _token Address of the GRT (mock) token\n * @param _manager Address of the wallet's manager\n * @param _isInitialized Whether the wallet has been initialized\n * @param _isAccepted Whether the beneficiary has accepted the lock\n */\n constructor(address _target, address _token, address _manager, bool _isInitialized, bool _isAccepted) {\n target = _target;\n token = _token;\n manager = _manager;\n isInitialized = _isInitialized;\n isAccepted = _isAccepted;\n }\n\n /**\n * @notice Fallback function\n * @dev This function calls the target contract with the data sent to this contract.\n * This is used to test the L1-L2 transfer tool.\n */\n fallback() external payable {\n // Call function with data\n Address.functionCall(target, msg.data);\n }\n\n /**\n * @notice Receive function\n * @dev This function is added to avoid compiler warnings, but just reverts.\n */\n receive() external payable {\n revert(\"Invalid call\");\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-one/.chainId b/packages/token-distribution/deployments/arbitrum-one/.chainId new file mode 100644 index 000000000..7df83ecbe --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-one/.chainId @@ -0,0 +1 @@ +42161 \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-Foundation-v1.json b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-Foundation-v1.json new file mode 100644 index 000000000..5118e146d --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-Foundation-v1.json @@ -0,0 +1,1161 @@ +{ + "address": "0x4f74c728CEe713191E500e68a8C8cC32bff9d911", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1TransferTool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Address", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedTokensReceivedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "TokenLockCreatedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1TransferTool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l1WalletToL2Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletToL1Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x7e5d9b96ea7bdce06eea3febf62543c269b4f4a9e2a03a5be0dad97ca14b3564", + "receipt": { + "to": null, + "from": "0x4528FD7868c91Ef64B9907450Ee8d82dC639612c", + "contractAddress": "0x4f74c728CEe713191E500e68a8C8cC32bff9d911", + "transactionIndex": 1, + "gasUsed": "25715468", + "logsBloom": "0x00000000000000200000200000000000000004000000000100800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000200000000001000000000000000000400000000002000000020000000000000000000800000000000000000000000000000000400000002000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000020000000000000000000", + "blockHash": "0x8b77a265ed1e911a014daec707ce98c5c0764980b4151dbd09679fd936fe4369", + "transactionHash": "0x7e5d9b96ea7bdce06eea3febf62543c269b4f4a9e2a03a5be0dad97ca14b3564", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 113597444, + "transactionHash": "0x7e5d9b96ea7bdce06eea3febf62543c269b4f4a9e2a03a5be0dad97ca14b3564", + "address": "0x4f74c728CEe713191E500e68a8C8cC32bff9d911", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004528fd7868c91ef64b9907450ee8d82dc639612c" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x8b77a265ed1e911a014daec707ce98c5c0764980b4151dbd09679fd936fe4369" + }, + { + "transactionIndex": 1, + "blockNumber": 113597444, + "transactionHash": "0x7e5d9b96ea7bdce06eea3febf62543c269b4f4a9e2a03a5be0dad97ca14b3564", + "address": "0x4f74c728CEe713191E500e68a8C8cC32bff9d911", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x0000000000000000000000006864cdd6d69dbef02e5e06c5534b20fdaf8b51b0" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x8b77a265ed1e911a014daec707ce98c5c0764980b4151dbd09679fd936fe4369" + } + ], + "blockNumber": 113597444, + "cumulativeGasUsed": "25715468", + "status": 1, + "byzantium": true + }, + "args": [ + "0x9623063377AD1B27544C965cCd7342f7EA7e88C7", + "0x6864Cdd6D69Dbef02E5e06c5534b20fdaf8b51b0", + "0x65E1a5e8946e7E87d9774f5288f41c30a99fD302", + "0xCa82c7Ce3388b0B5d307574099aC57d7a00d509F" + ], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Gateway\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l1TransferTool\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Address\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LockedTokensReceivedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"}],\"name\":\"TokenLockCreatedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1TransferTool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l1WalletToL2Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l2WalletToL1Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"LockedTokensReceivedFromL1(address,address,uint256)\":{\"details\":\"Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)\"},\"TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)\":{\"details\":\"Event emitted when a wallet is received and created from L1\"}},\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Address of the L2 GRT token contract\",\"_l1TransferTool\":\"Address of the L1 transfer tool contract (in L1, without aliasing)\",\"_l2Gateway\":\"Address of the L2GraphTokenGateway contract\",\"_masterCopy\":\"Address of the master copy of the L2GraphTokenLockWallet implementation\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"onTokenTransfer(address,uint256,bytes)\":{\"details\":\"This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.\",\"params\":{\"_amount\":\"Amount of tokens received\",\"_data\":\"Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\",\"_from\":\"Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor for the L2GraphTokenLockManager contract.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"l1TransferTool()\":{\"notice\":\"Address of the L1 transfer tool contract (in L1, no aliasing)\"},\"l1WalletToL2Wallet(address)\":{\"notice\":\"Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address\"},\"l2Gateway()\":{\"notice\":\"Address of the L2GraphTokenGateway\"},\"l2WalletToL1Wallet(address)\":{\"notice\":\"Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address\"},\"onTokenTransfer(address,uint256,bytes)\":{\"notice\":\"This function is called by the L2GraphTokenGateway when tokens are sent from L1.\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockManager.sol\":\"L2GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200499938038062004999833981810160405281019062000037919062000410565b838360006200004b6200022860201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001539062000586565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ae816200023060201b60201c565b50508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250505050505062000635565b600033905090565b620002406200022860201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1662000266620003b960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620002bf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b69062000564565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000332576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003299062000542565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600081519050620003f38162000601565b92915050565b6000815190506200040a816200061b565b92915050565b600080600080608085870312156200042757600080fd5b60006200043787828801620003f9565b94505060206200044a87828801620003e2565b93505060406200045d87828801620003e2565b92505060606200047087828801620003e2565b91505092959194509250565b60006200048b601983620005a8565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000620004cd602083620005a8565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200050f601483620005a8565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b600060208201905081810360008301526200055d816200047c565b9050919050565b600060208201905081810360008301526200057f81620004be565b9050919050565b60006020820190508181036000830152620005a18162000500565b9050919050565b600082825260208201905092915050565b6000620005c682620005e1565b9050919050565b6000620005da82620005b9565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200060c81620005b9565b81146200061857600080fd5b50565b6200062681620005cd565b81146200063257600080fd5b50565b60805160601c60a05160601c61433062000669600039806109195280611280525080610fc952806111f252506143306000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "devdoc": { + "events": { + "LockedTokensReceivedFromL1(address,address,uint256)": { + "details": "Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)" + }, + "TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)": { + "details": "Event emitted when a wallet is received and created from L1" + } + }, + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Address of the L2 GRT token contract", + "_l1TransferTool": "Address of the L1 transfer tool contract (in L1, without aliasing)", + "_l2Gateway": "Address of the L2GraphTokenGateway contract", + "_masterCopy": "Address of the master copy of the L2GraphTokenLockWallet implementation" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "onTokenTransfer(address,uint256,bytes)": { + "details": "This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.", + "params": { + "_amount": "Amount of tokens received", + "_data": "Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct", + "_from": "Address of the sender in L1, which must be the L1GraphTokenLockTransferTool" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor for the L2GraphTokenLockManager contract." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "l1TransferTool()": { + "notice": "Address of the L1 transfer tool contract (in L1, no aliasing)" + }, + "l1WalletToL2Wallet(address)": { + "notice": "Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address" + }, + "l2Gateway()": { + "notice": "Address of the L2GraphTokenGateway" + }, + "l2WalletToL1Wallet(address)": { + "notice": "Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address" + }, + "onTokenTransfer(address,uint256,bytes)": { + "notice": "This function is called by the L2GraphTokenGateway when tokens are sent from L1." + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 6154, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l1WalletToL2Wallet", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 6159, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l2WalletToL1Wallet", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-MIPs.json b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-MIPs.json new file mode 100644 index 000000000..8ef6613eb --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-MIPs.json @@ -0,0 +1,1161 @@ +{ + "address": "0xf2F89D0bB013c9c292B8E398903e421a1028bDA5", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1TransferTool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Address", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedTokensReceivedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "TokenLockCreatedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1TransferTool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l1WalletToL2Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletToL1Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xda00bc8ee16463f5491e1d0d5406d2068a44986ad87a7a81c1f8b94ed284e954", + "receipt": { + "to": null, + "from": "0x4528FD7868c91Ef64B9907450Ee8d82dC639612c", + "contractAddress": "0xf2F89D0bB013c9c292B8E398903e421a1028bDA5", + "transactionIndex": 3, + "gasUsed": "26151593", + "logsBloom": "0x00000000000000200000200000000000000004000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000001000000000000000000400000000002000000020000000000000000000800000000000000000000000000000000400000002000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000010000000004000020000", + "blockHash": "0xce6940bbead1193970faa244e6434732ef3bd91cbc9a2c47e80eec17b9d5647f", + "transactionHash": "0xda00bc8ee16463f5491e1d0d5406d2068a44986ad87a7a81c1f8b94ed284e954", + "logs": [ + { + "transactionIndex": 3, + "blockNumber": 113600719, + "transactionHash": "0xda00bc8ee16463f5491e1d0d5406d2068a44986ad87a7a81c1f8b94ed284e954", + "address": "0xf2F89D0bB013c9c292B8E398903e421a1028bDA5", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004528fd7868c91ef64b9907450ee8d82dc639612c" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0xce6940bbead1193970faa244e6434732ef3bd91cbc9a2c47e80eec17b9d5647f" + }, + { + "transactionIndex": 3, + "blockNumber": 113600719, + "transactionHash": "0xda00bc8ee16463f5491e1d0d5406d2068a44986ad87a7a81c1f8b94ed284e954", + "address": "0xf2F89D0bB013c9c292B8E398903e421a1028bDA5", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x0000000000000000000000006864cdd6d69dbef02e5e06c5534b20fdaf8b51b0" + ], + "data": "0x", + "logIndex": 2, + "blockHash": "0xce6940bbead1193970faa244e6434732ef3bd91cbc9a2c47e80eec17b9d5647f" + } + ], + "blockNumber": 113600719, + "cumulativeGasUsed": "27174901", + "status": 1, + "byzantium": true + }, + "args": [ + "0x9623063377AD1B27544C965cCd7342f7EA7e88C7", + "0x6864Cdd6D69Dbef02E5e06c5534b20fdaf8b51b0", + "0x65E1a5e8946e7E87d9774f5288f41c30a99fD302", + "0xCa82c7Ce3388b0B5d307574099aC57d7a00d509F" + ], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Gateway\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l1TransferTool\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Address\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LockedTokensReceivedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"}],\"name\":\"TokenLockCreatedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1TransferTool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l1WalletToL2Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l2WalletToL1Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"LockedTokensReceivedFromL1(address,address,uint256)\":{\"details\":\"Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)\"},\"TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)\":{\"details\":\"Event emitted when a wallet is received and created from L1\"}},\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Address of the L2 GRT token contract\",\"_l1TransferTool\":\"Address of the L1 transfer tool contract (in L1, without aliasing)\",\"_l2Gateway\":\"Address of the L2GraphTokenGateway contract\",\"_masterCopy\":\"Address of the master copy of the L2GraphTokenLockWallet implementation\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"onTokenTransfer(address,uint256,bytes)\":{\"details\":\"This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.\",\"params\":{\"_amount\":\"Amount of tokens received\",\"_data\":\"Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\",\"_from\":\"Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor for the L2GraphTokenLockManager contract.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"l1TransferTool()\":{\"notice\":\"Address of the L1 transfer tool contract (in L1, no aliasing)\"},\"l1WalletToL2Wallet(address)\":{\"notice\":\"Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address\"},\"l2Gateway()\":{\"notice\":\"Address of the L2GraphTokenGateway\"},\"l2WalletToL1Wallet(address)\":{\"notice\":\"Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address\"},\"onTokenTransfer(address,uint256,bytes)\":{\"notice\":\"This function is called by the L2GraphTokenGateway when tokens are sent from L1.\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockManager.sol\":\"L2GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200499938038062004999833981810160405281019062000037919062000410565b838360006200004b6200022860201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001539062000586565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ae816200023060201b60201c565b50508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250505050505062000635565b600033905090565b620002406200022860201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1662000266620003b960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620002bf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b69062000564565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000332576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003299062000542565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600081519050620003f38162000601565b92915050565b6000815190506200040a816200061b565b92915050565b600080600080608085870312156200042757600080fd5b60006200043787828801620003f9565b94505060206200044a87828801620003e2565b93505060406200045d87828801620003e2565b92505060606200047087828801620003e2565b91505092959194509250565b60006200048b601983620005a8565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000620004cd602083620005a8565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200050f601483620005a8565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b600060208201905081810360008301526200055d816200047c565b9050919050565b600060208201905081810360008301526200057f81620004be565b9050919050565b60006020820190508181036000830152620005a18162000500565b9050919050565b600082825260208201905092915050565b6000620005c682620005e1565b9050919050565b6000620005da82620005b9565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200060c81620005b9565b81146200061857600080fd5b50565b6200062681620005cd565b81146200063257600080fd5b50565b60805160601c60a05160601c61433062000669600039806109195280611280525080610fc952806111f252506143306000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "devdoc": { + "events": { + "LockedTokensReceivedFromL1(address,address,uint256)": { + "details": "Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)" + }, + "TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)": { + "details": "Event emitted when a wallet is received and created from L1" + } + }, + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Address of the L2 GRT token contract", + "_l1TransferTool": "Address of the L1 transfer tool contract (in L1, without aliasing)", + "_l2Gateway": "Address of the L2GraphTokenGateway contract", + "_masterCopy": "Address of the master copy of the L2GraphTokenLockWallet implementation" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "onTokenTransfer(address,uint256,bytes)": { + "details": "This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.", + "params": { + "_amount": "Amount of tokens received", + "_data": "Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct", + "_from": "Address of the sender in L1, which must be the L1GraphTokenLockTransferTool" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor for the L2GraphTokenLockManager contract." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "l1TransferTool()": { + "notice": "Address of the L1 transfer tool contract (in L1, no aliasing)" + }, + "l1WalletToL2Wallet(address)": { + "notice": "Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address" + }, + "l2Gateway()": { + "notice": "Address of the L2GraphTokenGateway" + }, + "l2WalletToL1Wallet(address)": { + "notice": "Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address" + }, + "onTokenTransfer(address,uint256,bytes)": { + "notice": "This function is called by the L2GraphTokenGateway when tokens are sent from L1." + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 6154, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l1WalletToL2Wallet", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 6159, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l2WalletToL1Wallet", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager.json b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager.json new file mode 100644 index 000000000..f3aff0d3b --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager.json @@ -0,0 +1,1161 @@ +{ + "address": "0xF1ef3f2007E63cAA4F3B8e22D73B31CCF434500D", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1TransferTool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Address", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedTokensReceivedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "TokenLockCreatedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1TransferTool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l1WalletToL2Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletToL1Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x9e01867e9d647a91c2607bcf14fa3d106edff3d0010c593ee9535854ac1a4a72", + "receipt": { + "to": null, + "from": "0x4528FD7868c91Ef64B9907450Ee8d82dC639612c", + "contractAddress": "0xF1ef3f2007E63cAA4F3B8e22D73B31CCF434500D", + "transactionIndex": 1, + "gasUsed": "26151593", + "logsBloom": "0x00004000000000200000200100000000000004000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000001000000000000000000400000000002000000020000000000000000000800000000000000000000000000000000400000002000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8a49288c8778e5b27f878e249cf123940a27ce6b026ed980e94ccd65813647ac", + "transactionHash": "0x9e01867e9d647a91c2607bcf14fa3d106edff3d0010c593ee9535854ac1a4a72", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 113600391, + "transactionHash": "0x9e01867e9d647a91c2607bcf14fa3d106edff3d0010c593ee9535854ac1a4a72", + "address": "0xF1ef3f2007E63cAA4F3B8e22D73B31CCF434500D", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000004528fd7868c91ef64b9907450ee8d82dc639612c" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x8a49288c8778e5b27f878e249cf123940a27ce6b026ed980e94ccd65813647ac" + }, + { + "transactionIndex": 1, + "blockNumber": 113600391, + "transactionHash": "0x9e01867e9d647a91c2607bcf14fa3d106edff3d0010c593ee9535854ac1a4a72", + "address": "0xF1ef3f2007E63cAA4F3B8e22D73B31CCF434500D", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x0000000000000000000000006864cdd6d69dbef02e5e06c5534b20fdaf8b51b0" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x8a49288c8778e5b27f878e249cf123940a27ce6b026ed980e94ccd65813647ac" + } + ], + "blockNumber": 113600391, + "cumulativeGasUsed": "26151593", + "status": 1, + "byzantium": true + }, + "args": [ + "0x9623063377AD1B27544C965cCd7342f7EA7e88C7", + "0x6864Cdd6D69Dbef02E5e06c5534b20fdaf8b51b0", + "0x65E1a5e8946e7E87d9774f5288f41c30a99fD302", + "0xCa82c7Ce3388b0B5d307574099aC57d7a00d509F" + ], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Gateway\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l1TransferTool\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Address\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LockedTokensReceivedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"}],\"name\":\"TokenLockCreatedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1TransferTool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l1WalletToL2Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l2WalletToL1Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"LockedTokensReceivedFromL1(address,address,uint256)\":{\"details\":\"Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)\"},\"TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)\":{\"details\":\"Event emitted when a wallet is received and created from L1\"}},\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Address of the L2 GRT token contract\",\"_l1TransferTool\":\"Address of the L1 transfer tool contract (in L1, without aliasing)\",\"_l2Gateway\":\"Address of the L2GraphTokenGateway contract\",\"_masterCopy\":\"Address of the master copy of the L2GraphTokenLockWallet implementation\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"onTokenTransfer(address,uint256,bytes)\":{\"details\":\"This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.\",\"params\":{\"_amount\":\"Amount of tokens received\",\"_data\":\"Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\",\"_from\":\"Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor for the L2GraphTokenLockManager contract.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"l1TransferTool()\":{\"notice\":\"Address of the L1 transfer tool contract (in L1, no aliasing)\"},\"l1WalletToL2Wallet(address)\":{\"notice\":\"Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address\"},\"l2Gateway()\":{\"notice\":\"Address of the L2GraphTokenGateway\"},\"l2WalletToL1Wallet(address)\":{\"notice\":\"Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address\"},\"onTokenTransfer(address,uint256,bytes)\":{\"notice\":\"This function is called by the L2GraphTokenGateway when tokens are sent from L1.\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockManager.sol\":\"L2GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200499938038062004999833981810160405281019062000037919062000410565b838360006200004b6200022860201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001539062000586565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ae816200023060201b60201c565b50508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250505050505062000635565b600033905090565b620002406200022860201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1662000266620003b960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620002bf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b69062000564565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000332576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003299062000542565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600081519050620003f38162000601565b92915050565b6000815190506200040a816200061b565b92915050565b600080600080608085870312156200042757600080fd5b60006200043787828801620003f9565b94505060206200044a87828801620003e2565b93505060406200045d87828801620003e2565b92505060606200047087828801620003e2565b91505092959194509250565b60006200048b601983620005a8565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000620004cd602083620005a8565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200050f601483620005a8565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b600060208201905081810360008301526200055d816200047c565b9050919050565b600060208201905081810360008301526200057f81620004be565b9050919050565b60006020820190508181036000830152620005a18162000500565b9050919050565b600082825260208201905092915050565b6000620005c682620005e1565b9050919050565b6000620005da82620005b9565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200060c81620005b9565b81146200061857600080fd5b50565b6200062681620005cd565b81146200063257600080fd5b50565b60805160601c60a05160601c61433062000669600039806109195280611280525080610fc952806111f252506143306000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101735760003560e01c806379ee1bdf116100de578063a619486e11610097578063cf497e6c11610071578063cf497e6c14610434578063f1d24c4514610450578063f2fde38b14610480578063fc0c546a1461049c57610173565b8063a619486e146103de578063b6b55f25146103fc578063c1ab13db1461041857610173565b806379ee1bdf1461031c5780638da5cb5b1461034c5780638fa74a0e1461036a5780639c05fc6014610388578063a3457466146103a4578063a4c0ed36146103c257610173565b8063463013a211610130578063463013a214610270578063586a53531461028c5780635975e00c146102aa57806368d30c2e146102c65780636e03b8dc146102e2578063715018a61461031257610173565b806303990a6c14610178578063045b7fe2146101945780630602ba2b146101c45780630cd6178f146101f45780632e1a7d4d1461022457806343fb93d914610240575b600080fd5b610192600480360381019061018d9190612f13565b6104ba565b005b6101ae60048036038101906101a99190612ca2565b610662565b6040516101bb91906139bc565b60405180910390f35b6101de60048036038101906101d99190612eea565b610695565b6040516101eb9190613bba565b60405180910390f35b61020e60048036038101906102099190612ca2565b6106d6565b60405161021b91906139bc565b60405180910390f35b61023e60048036038101906102399190612fd9565b610709565b005b61025a60048036038101906102559190612e9b565b610866565b60405161026791906139bc565b60405180910390f35b61028a60048036038101906102859190612f58565b61088b565b005b610294610917565b6040516102a191906139bc565b60405180910390f35b6102c460048036038101906102bf9190612ca2565b61093b565b005b6102e060048036038101906102db9190612ccb565b610acc565b005b6102fc60048036038101906102f79190612eea565b610e14565b60405161030991906139bc565b60405180910390f35b61031a610e47565b005b61033660048036038101906103319190612ca2565b610f81565b6040516103439190613bba565b60405180910390f35b610354610f9e565b60405161036191906139bc565b60405180910390f35b610372610fc7565b60405161037f91906139bc565b60405180910390f35b6103a2600480360381019061039d9190612dfd565b610feb565b005b6103ac611118565b6040516103b99190613b98565b60405180910390f35b6103dc60048036038101906103d79190612d91565b6111f0565b005b6103e6611756565b6040516103f391906139bc565b60405180910390f35b61041660048036038101906104119190612fd9565b61177c565b005b610432600480360381019061042d9190612ca2565b61185f565b005b61044e60048036038101906104499190612ca2565b611980565b005b61046a60048036038101906104659190612eea565b611af3565b60405161047791906139bc565b60405180910390f35b61049a60048036038101906104959190612ca2565b611b6e565b005b6104a4611d17565b6040516104b19190613c1a565b60405180910390f35b6104c2611d41565b73ffffffffffffffffffffffffffffffffffffffff166104e0610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610536576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052d90613e3b565b60405180910390fd5b60006105428383611d49565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610655929190613c35565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff166106b783611af3565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610711611d41565b73ffffffffffffffffffffffffffffffffffffffff1661072f610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610785576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077c90613e3b565b60405180910390fd5b600081116107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613e1b565b60405180910390fd5b6108153382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b8260405161085b9190613f1b565b60405180910390a250565b60006108828461087585611e5d565b8051906020012084611ed3565b90509392505050565b610893611d41565b73ffffffffffffffffffffffffffffffffffffffff166108b1610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610907576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108fe90613e3b565b60405180910390fd5b610912838383611f17565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b610943611d41565b73ffffffffffffffffffffffffffffffffffffffff16610961610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146109b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109ae90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a1e90613cfb565b60405180910390fd5b610a3b8160026120f990919063ffffffff16565b610a7a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7190613e7b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610ac19190613bba565b60405180910390a250565b610ad4611d41565b73ffffffffffffffffffffffffffffffffffffffff16610af2610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610b48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3f90613e3b565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610ba491906139bc565b60206040518083038186803b158015610bbc57600080fd5b505afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190613002565b1015610c35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c2c90613d3b565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610c869b9a999897969594939291906139d7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d1b8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b9050610d6a818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610dff989796959493929190613b1a565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e4f611d41565b73ffffffffffffffffffffffffffffffffffffffff16610e6d610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614610ec3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eba90613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610f978260026121a590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b610ff3611d41565b73ffffffffffffffffffffffffffffffffffffffff16611011610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611067576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161105e90613e3b565b60405180910390fd5b8181905084849050146110af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a690613cbb565b60405180910390fd5b60005b84849050811015611111576111048585838181106110cc57fe5b90506020028101906110de9190613f36565b8585858181106110ea57fe5b90506020020160208101906110ff9190612ca2565b611f17565b80806001019150506110b2565b5050505050565b60608061112560026121d5565b67ffffffffffffffff8111801561113b57600080fd5b5060405190808252806020026020018201604052801561116a5781602001602082028036833780820191505090505b50905060005b61117a60026121d5565b8110156111e8576111958160026121ea90919063ffffffff16565b8282815181106111a157fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611170565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461127e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161127590613cdb565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161461130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390613d7b565b60405180910390fd5b6113146129d3565b82828101906113239190612fb0565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114715761146c60066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b611683565b6000806114958585604051611487929190613973565b604051809103902084612204565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506115ea8187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611dd79092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116789493929190613bd5565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117479190613f1b565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116117bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117b690613e1b565b60405180910390fd5b61180e333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661225b909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516118549190613f1b565b60405180910390a250565b611867611d41565b73ffffffffffffffffffffffffffffffffffffffff16611885610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146118db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118d290613e3b565b60405180910390fd5b6118ef8160026122e490919063ffffffff16565b61192e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161192590613d9b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119759190613bba565b60405180910390a250565b611988611d41565b73ffffffffffffffffffffffffffffffffffffffff166119a6610f9e565b73ffffffffffffffffffffffffffffffffffffffff16146119fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119f390613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611a6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a6390613dbb565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611b76611d41565b73ffffffffffffffffffffffffffffffffffffffff16611b94610f9e565b73ffffffffffffffffffffffffffffffffffffffff1614611bea576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be190613e3b565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611c5a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c5190613d1b565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611dcf83836040516024016040516020818303038152906040529190604051611d759291906139a3565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612314565b905092915050565b611e588363a9059cbb60e01b8484604051602401611df6929190613af1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611eb994939291906138d7565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611ef19493929190613925565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7d90613ddb565b60405180910390fd5b611f8f81612433565b611fce576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fc590613efb565b60405180910390fd5b6000611fda8484611d49565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516120eb929190613c35565b60405180910390a450505050565b6000612121836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612446565b905092915050565b60008061214060008661213b87611e5d565b6124b6565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a260008351111561219a5761219881846125c7565b505b809150509392505050565b60006121cd836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612611565b905092915050565b60006121e382600001612634565b9050919050565b60006121f98360000183612645565b60001c905092915050565b6000806060612212846126b2565b9050600061224386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612129565b90508180519060200120819350935050509250929050565b6122de846323b872dd60e01b85858560405160240161227c93929190613aba565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061236c565b50505050565b600061230c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612757565b905092915050565b6000600482511461235a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161235190613e5b565b60405180910390fd5b60006020830151905080915050919050565b60606123ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661283f9092919063ffffffff16565b905060008151111561242e57808060200190518101906123ee9190612e72565b61242d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161242490613ebb565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124528383612611565b6124ab5782600001829080600181540180825580915050600190039060005260206000200160009091909190915055826000018054905083600101600084815260200190815260200160002081905550600190506124b0565b600090505b92915050565b600080844710156124fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f390613edb565b60405180910390fd5b600083511415612541576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161253890613c9b565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156125bc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125b390613dfb565b60405180910390fd5b809150509392505050565b606061260983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061283f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612690576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161268790613c7b565b60405180910390fd5b82600001828154811061269f57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040516024016126f393929190613a82565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b6000808360010160008481526020019081526020016000205490506000811461283357600060018203905060006001866000018054905003905060008660000182815481106127a257fe5b90600052602060002001549050808760000184815481106127bf57fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806127f757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612839565b60009150505b92915050565b606061284e8484600085612857565b90509392505050565b60608247101561289c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161289390613d5b565b60405180910390fd5b6128a585612433565b6128e4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128db90613e9b565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161290e919061398c565b60006040518083038185875af1925050503d806000811461294b576040519150601f19603f3d011682016040523d82523d6000602084013e612950565b606091505b509150915061296082828661296c565b92505050949350505050565b6060831561297c578290506129cc565b60008351111561298f5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129c39190613c59565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612a5a81614277565b92915050565b60008083601f840112612a7257600080fd5b8235905067ffffffffffffffff811115612a8b57600080fd5b602083019150836020820283011115612aa357600080fd5b9250929050565b60008083601f840112612abc57600080fd5b8235905067ffffffffffffffff811115612ad557600080fd5b602083019150836020820283011115612aed57600080fd5b9250929050565b600081519050612b038161428e565b92915050565b600081359050612b18816142a5565b92915050565b600081359050612b2d816142bc565b92915050565b60008083601f840112612b4557600080fd5b8235905067ffffffffffffffff811115612b5e57600080fd5b602083019150836001820283011115612b7657600080fd5b9250929050565b600081359050612b8c816142d3565b92915050565b60008083601f840112612ba457600080fd5b8235905067ffffffffffffffff811115612bbd57600080fd5b602083019150836001820283011115612bd557600080fd5b9250929050565b600060c08284031215612bee57600080fd5b612bf860c0613f8d565b90506000612c0884828501612a4b565b6000830152506020612c1c84828501612a4b565b6020830152506040612c3084828501612a4b565b6040830152506060612c4484828501612c78565b6060830152506080612c5884828501612c78565b60808301525060a0612c6c84828501612c78565b60a08301525092915050565b600081359050612c87816142e3565b92915050565b600081519050612c9c816142e3565b92915050565b600060208284031215612cb457600080fd5b6000612cc284828501612a4b565b91505092915050565b60008060008060008060008060006101208a8c031215612cea57600080fd5b6000612cf88c828d01612a4b565b9950506020612d098c828d01612a4b565b9850506040612d1a8c828d01612c78565b9750506060612d2b8c828d01612c78565b9650506080612d3c8c828d01612c78565b95505060a0612d4d8c828d01612c78565b94505060c0612d5e8c828d01612c78565b93505060e0612d6f8c828d01612c78565b925050610100612d818c828d01612b7d565b9150509295985092959850929598565b60008060008060608587031215612da757600080fd5b6000612db587828801612a4b565b9450506020612dc687828801612c78565b935050604085013567ffffffffffffffff811115612de357600080fd5b612def87828801612b33565b925092505092959194509250565b60008060008060408587031215612e1357600080fd5b600085013567ffffffffffffffff811115612e2d57600080fd5b612e3987828801612aaa565b9450945050602085013567ffffffffffffffff811115612e5857600080fd5b612e6487828801612a60565b925092505092959194509250565b600060208284031215612e8457600080fd5b6000612e9284828501612af4565b91505092915050565b600080600060608486031215612eb057600080fd5b6000612ebe86828701612b09565b9350506020612ecf86828701612a4b565b9250506040612ee086828701612a4b565b9150509250925092565b600060208284031215612efc57600080fd5b6000612f0a84828501612b1e565b91505092915050565b60008060208385031215612f2657600080fd5b600083013567ffffffffffffffff811115612f4057600080fd5b612f4c85828601612b92565b92509250509250929050565b600080600060408486031215612f6d57600080fd5b600084013567ffffffffffffffff811115612f8757600080fd5b612f9386828701612b92565b93509350506020612fa686828701612a4b565b9150509250925092565b600060c08284031215612fc257600080fd5b6000612fd084828501612bdc565b91505092915050565b600060208284031215612feb57600080fd5b6000612ff984828501612c78565b91505092915050565b60006020828403121561301457600080fd5b600061302284828501612c8d565b91505092915050565b60006130378383613043565b60208301905092915050565b61304c81614034565b82525050565b61305b81614034565b82525050565b61307261306d82614034565b6141ed565b82525050565b600061308382613fce565b61308d8185613ffc565b935061309883613fbe565b8060005b838110156130c95781516130b0888261302b565b97506130bb83613fef565b92505060018101905061309c565b5085935050505092915050565b6130df81614046565b82525050565b6130f66130f18261407e565b614209565b82525050565b61310d613108826140aa565b614213565b82525050565b61312461311f82614052565b6141ff565b82525050565b61313b613136826140d6565b61421d565b82525050565b61314a81614102565b82525050565b61316161315c82614102565b614227565b82525050565b6000613173838561400d565b93506131808385846141ab565b82840190509392505050565b600061319782613fd9565b6131a1818561400d565b93506131b18185602086016141ba565b80840191505092915050565b6131c681614175565b82525050565b6131d581614199565b82525050565b60006131e78385614018565b93506131f48385846141ab565b6131fd83614245565b840190509392505050565b60006132148385614029565b93506132218385846141ab565b82840190509392505050565b600061323882613fe4565b6132428185614018565b93506132528185602086016141ba565b61325b81614245565b840191505092915050565b6000613273602283614018565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006132d9602083614018565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b6000613319601583614018565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000613359600c83614018565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613399601a83614018565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006133d9602683614018565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061343f602083614018565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061347f602683614018565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134e5601283614018565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b6000613525601b83614018565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000613565601983614018565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006135a5601d83614018565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006135e5601983614018565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000613625601583614018565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613665602083614018565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006136a5601883614018565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006136e5601983614018565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000613725601d83614018565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613765602a83614018565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cb601d83614018565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b600061380b601983614018565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138546000850182613043565b5060208201516138676020850182613043565b50604082015161387a6040850182613043565b50606082015161388d60608501826138b9565b5060808201516138a060808501826138b9565b5060a08201516138b360a08501826138b9565b50505050565b6138c28161416b565b82525050565b6138d18161416b565b82525050565b60006138e382876130e5565b600a820191506138f382866130e5565b600a82019150613903828561312a565b60148201915061391382846130fc565b600f8201915081905095945050505050565b60006139318287613113565b6001820191506139418286613061565b6014820191506139518285613150565b6020820191506139618284613150565b60208201915081905095945050505050565b6000613980828486613167565b91508190509392505050565b6000613998828461318c565b915081905092915050565b60006139b0828486613208565b91508190509392505050565b60006020820190506139d16000830184613052565b92915050565b6000610160820190506139ed600083018e613052565b6139fa602083018d613052565b613a07604083018c613052565b613a14606083018b613052565b613a21608083018a6138c8565b613a2e60a08301896138c8565b613a3b60c08301886138c8565b613a4860e08301876138c8565b613a566101008301866138c8565b613a646101208301856138c8565b613a726101408301846131cc565b9c9b505050505050505050505050565b600061010082019050613a986000830186613052565b613aa56020830185613052565b613ab2604083018461383e565b949350505050565b6000606082019050613acf6000830186613052565b613adc6020830185613052565b613ae960408301846138c8565b949350505050565b6000604082019050613b066000830185613052565b613b1360208301846138c8565b9392505050565b600061010082019050613b30600083018b613052565b613b3d602083018a6138c8565b613b4a60408301896138c8565b613b5760608301886138c8565b613b6460808301876138c8565b613b7160a08301866138c8565b613b7e60c08301856138c8565b613b8b60e08301846131cc565b9998505050505050505050565b60006020820190508181036000830152613bb28184613078565b905092915050565b6000602082019050613bcf60008301846130d6565b92915050565b6000608082019050613bea6000830187613141565b613bf760208301866138c8565b613c0460408301856138c8565b613c1160608301846138c8565b95945050505050565b6000602082019050613c2f60008301846131bd565b92915050565b60006020820190508181036000830152613c508184866131db565b90509392505050565b60006020820190508181036000830152613c73818461322d565b905092915050565b60006020820190508181036000830152613c9481613266565b9050919050565b60006020820190508181036000830152613cb4816132cc565b9050919050565b60006020820190508181036000830152613cd48161330c565b9050919050565b60006020820190508181036000830152613cf48161334c565b9050919050565b60006020820190508181036000830152613d148161338c565b9050919050565b60006020820190508181036000830152613d34816133cc565b9050919050565b60006020820190508181036000830152613d5481613432565b9050919050565b60006020820190508181036000830152613d7481613472565b9050919050565b60006020820190508181036000830152613d94816134d8565b9050919050565b60006020820190508181036000830152613db481613518565b9050919050565b60006020820190508181036000830152613dd481613558565b9050919050565b60006020820190508181036000830152613df481613598565b9050919050565b60006020820190508181036000830152613e14816135d8565b9050919050565b60006020820190508181036000830152613e3481613618565b9050919050565b60006020820190508181036000830152613e5481613658565b9050919050565b60006020820190508181036000830152613e7481613698565b9050919050565b60006020820190508181036000830152613e94816136d8565b9050919050565b60006020820190508181036000830152613eb481613718565b9050919050565b60006020820190508181036000830152613ed481613758565b9050919050565b60006020820190508181036000830152613ef4816137be565b9050919050565b60006020820190508181036000830152613f14816137fe565b9050919050565b6000602082019050613f3060008301846138c8565b92915050565b60008083356001602003843603038112613f4f57600080fd5b80840192508235915067ffffffffffffffff821115613f6d57600080fd5b602083019250600182023603831315613f8557600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff82111715613fb457613fb3614243565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061403f8261414b565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061414682614263565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061418082614187565b9050919050565b60006141928261414b565b9050919050565b60006141a482614138565b9050919050565b82818337600083830152505050565b60005b838110156141d85780820151818401526020810190506141bd565b838111156141e7576000848401525b50505050565b60006141f882614231565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600061423c82614256565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061427457614273614243565b5b50565b61428081614034565b811461428b57600080fd5b50565b61429781614046565b81146142a257600080fd5b50565b6142ae81614102565b81146142b957600080fd5b50565b6142c58161410c565b81146142d057600080fd5b50565b600381106142e057600080fd5b50565b6142ec8161416b565b81146142f757600080fd5b5056fea264697066735822122010f167ec85dbd4b07aedb6960f9f6ac5ae1b0f5473409617dcd319393591837164736f6c63430007030033", + "devdoc": { + "events": { + "LockedTokensReceivedFromL1(address,address,uint256)": { + "details": "Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)" + }, + "TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)": { + "details": "Event emitted when a wallet is received and created from L1" + } + }, + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Address of the L2 GRT token contract", + "_l1TransferTool": "Address of the L1 transfer tool contract (in L1, without aliasing)", + "_l2Gateway": "Address of the L2GraphTokenGateway contract", + "_masterCopy": "Address of the master copy of the L2GraphTokenLockWallet implementation" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "onTokenTransfer(address,uint256,bytes)": { + "details": "This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.", + "params": { + "_amount": "Amount of tokens received", + "_data": "Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct", + "_from": "Address of the sender in L1, which must be the L1GraphTokenLockTransferTool" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor for the L2GraphTokenLockManager contract." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "l1TransferTool()": { + "notice": "Address of the L1 transfer tool contract (in L1, no aliasing)" + }, + "l1WalletToL2Wallet(address)": { + "notice": "Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address" + }, + "l2Gateway()": { + "notice": "Address of the L2GraphTokenGateway" + }, + "l2WalletToL1Wallet(address)": { + "notice": "Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address" + }, + "onTokenTransfer(address,uint256,bytes)": { + "notice": "This function is called by the L2GraphTokenGateway when tokens are sent from L1." + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 6154, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l1WalletToL2Wallet", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 6159, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l2WalletToL1Wallet", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockTransferTool.json b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockTransferTool.json new file mode 100644 index 000000000..d79990d2d --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockTransferTool.json @@ -0,0 +1,110 @@ +{ + "address": "0x23C9c8575E6bA0349a497b6D0E8F0b9239e68028", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "contract ITokenGateway", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1GraphToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedFundsSentToL1", + "type": "event" + }, + { + "inputs": [], + "name": "graphToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1GraphToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "contract ITokenGateway", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawToL1Locked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xecb5b61a0d6fbca8f01174fea87d34172d4321650ba0566b0a9c87c7eca8df73" +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockWallet.json b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockWallet.json new file mode 100644 index 000000000..f80fc8a4b --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockWallet.json @@ -0,0 +1,1156 @@ +{ + "address": "0x6864Cdd6D69Dbef02E5e06c5534b20fdaf8b51b0", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + } + ], + "internalType": "struct L2GraphTokenLockManager.TransferredWalletData", + "name": "_walletData", + "type": "tuple" + } + ], + "name": "initializeFromL1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x62d5d07e799bf37a4758be9f534d365caaf94bffd008ce65ff686ab50ca7c959", + "receipt": { + "to": null, + "from": "0x4528FD7868c91Ef64B9907450Ee8d82dC639612c", + "contractAddress": "0x6864Cdd6D69Dbef02E5e06c5534b20fdaf8b51b0", + "transactionIndex": 1, + "gasUsed": "40523081", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x53f3c15e6c6c7a7b162732859ee6c5066dc3a3a2c97b93157c5ad03c9967f636", + "transactionHash": "0x62d5d07e799bf37a4758be9f534d365caaf94bffd008ce65ff686ab50ca7c959", + "logs": [], + "blockNumber": 113551330, + "cumulativeGasUsed": "40523081", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"}],\"internalType\":\"struct L2GraphTokenLockManager.TransferredWalletData\",\"name\":\"_walletData\",\"type\":\"tuple\"}],\"name\":\"initializeFromL1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. This L2 variant includes a special initializer so that it can be created from a wallet's data received from L1. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1, so releasing surplus tokens might also only be possible by bridging tokens back to L1. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockWallet.sol\":\"L2GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506148f5806100206000396000f3fe6080604052600436106102605760003560e01c80637bdf05af11610144578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610bc7578063e8dda6f514610bf0578063e97d87d514610c1b578063ebbab99214610c46578063f2fde38b14610c71578063fc0c546a14610c9a576102a0565b8063bc0163c114610af4578063bd896dcb14610b1f578063ce845d1d14610b48578063d0ebdbe714610b73578063d18e81b314610b9c576102a0565b80638da5cb5b116101085780638da5cb5b14610a0857806391f7cfb914610a33578063a4caeb4214610a5e578063b0d1818c14610a89578063b470aade14610ab2578063b6549f7514610add576102a0565b80637bdf05af1461095957806386d00e021461098457806386d1a69f146109af578063872a7810146109c65780638a5bdf5c146109f1576102a0565b806338af3eed116101dd578063481c6a75116101a1578063481c6a751461087f5780635051a5ec146108aa5780635b940081146108d557806360e7994414610900578063715018a61461091757806378e979251461092e576102a0565b806338af3eed146107a8578063392e53cd146107d3578063398057a3146107fe57806344b1231f1461082957806345d30a1714610854576102a0565b806320dc203d1161022457806320dc203d146106e75780632a627814146107105780632bc9ed02146107275780633197cbb61461075257806337aeb0861461077d576102a0565b8063029c6c9f14610624578063060406181461064f5780630b80f7771461067a5780630dff24d5146106915780630fb5a6b4146106bc576102a0565b366102a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610297906141f3565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610327906143d3565b60405180910390fd5b60003414610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036a90614213565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103f49190614165565b60206040518083038186803b15801561040c57600080fd5b505afa158015610420573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610444919061338f565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ad906144d3565b60405180910390fd5b60006104c0610cc5565b9050610511826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d77565b506001600281111561051f57fe5b603b60009054906101000a900460ff16600281111561053a57fe5b141561062057600061054a610cc5565b90508181101561058c5760006105698284610dc190919063ffffffff16565b905061058081603f54610e1190919063ffffffff16565b603f81905550506105d2565b60006105a18383610dc190919063ffffffff16565b9050603f548110156105c7576105c281603f54610dc190919063ffffffff16565b6105ca565b60005b603f81905550505b6105da610e66565b603f54111561061e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061590614433565b60405180910390fd5b505b5050005b34801561063057600080fd5b50610639610ed5565b6040516106469190614673565b60405180910390f35b34801561065b57600080fd5b50610664610ef3565b6040516106719190614673565b60405180910390f35b34801561068657600080fd5b5061068f610f2e565b005b34801561069d57600080fd5b506106a661109b565b6040516106b39190614673565b60405180910390f35b3480156106c857600080fd5b506106d16110e2565b6040516106de9190614673565b60405180910390f35b3480156106f357600080fd5b5061070e600480360381019061070991906134a8565b611100565b005b34801561071c57600080fd5b5061072561129b565b005b34801561073357600080fd5b5061073c611500565b604051610749919061414a565b60405180910390f35b34801561075e57600080fd5b50610767611513565b6040516107749190614673565b60405180910390f35b34801561078957600080fd5b50610792611519565b60405161079f9190614673565b60405180910390f35b3480156107b457600080fd5b506107bd61151f565b6040516107ca91906140dd565b60405180910390f35b3480156107df57600080fd5b506107e8611545565b6040516107f5919061414a565b60405180910390f35b34801561080a57600080fd5b50610813611558565b6040516108209190614673565b60405180910390f35b34801561083557600080fd5b5061083e610e66565b60405161084b9190614673565b60405180910390f35b34801561086057600080fd5b5061086961155e565b6040516108769190614673565b60405180910390f35b34801561088b57600080fd5b50610894611564565b6040516108a1919061419b565b60405180910390f35b3480156108b657600080fd5b506108bf61158a565b6040516108cc919061414a565b60405180910390f35b3480156108e157600080fd5b506108ea61159d565b6040516108f79190614673565b60405180910390f35b34801561090c57600080fd5b506109156116a8565b005b34801561092357600080fd5b5061092c6118ee565b005b34801561093a57600080fd5b50610943611a3a565b6040516109509190614673565b60405180910390f35b34801561096557600080fd5b5061096e611a40565b60405161097b9190614673565b60405180910390f35b34801561099057600080fd5b50610999611a7c565b6040516109a69190614673565b60405180910390f35b3480156109bb57600080fd5b506109c4611a82565b005b3480156109d257600080fd5b506109db611c5e565b6040516109e891906141b6565b60405180910390f35b3480156109fd57600080fd5b50610a06611c71565b005b348015610a1457600080fd5b50610a1d611d4a565b604051610a2a91906140dd565b60405180910390f35b348015610a3f57600080fd5b50610a48611d73565b604051610a559190614673565b60405180910390f35b348015610a6a57600080fd5b50610a73611dd1565b604051610a809190614673565b60405180910390f35b348015610a9557600080fd5b50610ab06004803603810190610aab9190613562565b611dd7565b005b348015610abe57600080fd5b50610ac7611fd6565b604051610ad49190614673565b60405180910390f35b348015610ae957600080fd5b50610af2611ff9565b005b348015610b0057600080fd5b50610b09612291565b604051610b169190614673565b60405180910390f35b348015610b2b57600080fd5b50610b466004803603810190610b4191906133b8565b6122c3565b005b348015610b5457600080fd5b50610b5d610cc5565b604051610b6a9190614673565b60405180910390f35b348015610b7f57600080fd5b50610b9a6004803603810190610b959190613366565b6122eb565b005b348015610ba857600080fd5b50610bb1612385565b604051610bbe9190614673565b60405180910390f35b348015610bd357600080fd5b50610bee6004803603810190610be99190613366565b61238d565b005b348015610bfc57600080fd5b50610c05612508565b604051610c129190614673565b60405180910390f35b348015610c2757600080fd5b50610c3061250e565b604051610c3d9190614673565b60405180910390f35b348015610c5257600080fd5b50610c5b612514565b604051610c689190614673565b60405180910390f35b348015610c7d57600080fd5b50610c986004803603810190610c939190613366565b612536565b005b348015610ca657600080fd5b50610caf6126f1565b604051610cbc9190614180565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d2291906140dd565b60206040518083038186803b158015610d3a57600080fd5b505afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d72919061358b565b905090565b6060610db983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612717565b905092915050565b600082821115610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90614333565b60405180910390fd5b818303905092915050565b600080828401905083811015610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e53906142b3565b60405180910390fd5b8091505092915050565b6000600280811115610e7457fe5b603b60009054906101000a900460ff166002811115610e8f57fe5b1415610e9f576035549050610ed2565b6000603a54118015610eb95750603a54610eb7612385565b105b15610ec75760009050610ed2565b610ecf611d73565b90505b90565b6000610eee60385460355461272f90919063ffffffff16565b905090565b6000610f296001610f1b610f05611fd6565b610f0d611a40565b61272f90919063ffffffff16565b610e1190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb390614493565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514611012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100990614313565b60405180910390fd5b61106d61101d611d4a565b611025610cc5565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b6000806110a6610cc5565b905060006110b2612291565b9050808211156110d8576110cf8183610dc190919063ffffffff16565b925050506110df565b6000925050505b90565b60006110fb603654603754610dc190919063ffffffff16565b905090565b603b60029054906101000a900460ff1615611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114790614533565b60405180910390fd5b6001603b60026101000a81548160ff0219169083151502179055506111868160200160208101906111819190613366565b61280b565b8060400160208101906111999190613366565b603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806060013560358190555080608001356036819055508060a0013560378190555060016038819055506001603b60036101000a81548160ff0219169083151502179055508060a001356039819055506002603b60006101000a81548160ff0219169083600281111561128857fe5b0217905550611296836128a9565b505050565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132290614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561139557600080fd5b505afa1580156113a9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113d291906134f8565b905060005b81518110156114d057603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061142a57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b8152600401611470929190614121565b602060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c29190613539565b5080806001019150506113d7565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156115ab57fe5b603b60009054906101000a900460ff1660028111156115c657fe5b14156115db576115d4612a27565b90506116a5565b60006039541180156115f557506039546115f3612385565b105b1561160357600090506116a5565b6001600281111561161057fe5b603b60009054906101000a900460ff16600281111561162b57fe5b14801561163a57506000603a54115b801561164e5750603a5461164c612385565b105b1561165c57600090506116a5565b600061168e603f54611680603c54611672611d73565b610dc190919063ffffffff16565b610dc190919063ffffffff16565b90506116a161169b610cc5565b82612ae1565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172f90614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906117df91906134f8565b905060005b81518110156118be57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061183757fe5b602002602001015160006040518363ffffffff1660e01b815260040161185e9291906140f8565b602060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b09190613539565b5080806001019150506117e4565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197390614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b600080611a4b612385565b90506036548111611a60576000915050611a79565b611a7560365482610dc190919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0990614593565b60405180910390fd5b6000611b1c61159d565b905060008111611b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b58906145f3565b60405180910390fd5b611b7681603c54610e1190919063ffffffff16565b603c81905550611beb603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611c539190614673565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890614593565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611d7e612385565b9050603654811015611d94576000915050611dce565b603754811115611da957603554915050611dce565b611dca611db4610ed5565b611dbc612514565b612afa90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5e90614593565b60405180910390fd5b60008111611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea190614413565b60405180910390fd5b80611eb361109b565b1015611ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eeb90614513565b60405180910390fd5b611f63603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611fcb9190614673565b60405180910390a250565b6000611ff4603854611fe66110e2565b61272f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614493565b60405180910390fd5b6001600281111561209457fe5b603b60009054906101000a900460ff1660028111156120af57fe5b146120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614553565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213c90614653565b60405180910390fd5b6000612163612152610e66565b603554610dc190919063ffffffff16565b9050600081116121a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219f906142d3565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061221e6121d5611d4a565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516122869190614673565b60405180910390a250565b60006122be603d546122b0603c54603554610dc190919063ffffffff16565b610dc190919063ffffffff16565b905090565b6122d58a8a8a8a8a8a8a8a8a8a612b6a565b6122de8b6128a9565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237090614493565b60405180910390fd5b612382816128a9565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461241d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161241490614593565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561248d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612484906143b3565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d816040516124fd91906140dd565b60405180910390a150565b603f5481565b60395481565b60006125316001612523610ef3565b610dc190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bb90614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262b90614293565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606127268484600085612ff4565b90509392505050565b6000808211612773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276a90614393565b60405180910390fd5b81838161277c57fe5b04905092915050565b6128068363a9059cbb60e01b84846040516024016127a4929190614121565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613109565b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291090614573565b60405180910390fd5b612922816131d0565b612961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612958906143f3565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b600080603954118015612a425750603954612a40612385565b105b15612a505760009050612ade565b60016002811115612a5d57fe5b603b60009054906101000a900460ff166002811115612a7857fe5b148015612a8757506000603a54115b8015612a9b5750603a54612a99612385565b105b15612aa95760009050612ade565b6000612ac7603c54612ab9611d73565b610dc190919063ffffffff16565b9050612ada612ad4610cc5565b82612ae1565b9150505b90565b6000818310612af05781612af2565b825b905092915050565b600080831415612b0d5760009050612b64565b6000828402905082848281612b1e57fe5b0414612b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5690614473565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff1615612bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb190614533565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c21906142f3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190614633565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0190614613565b60405180910390fd5b60008711612d4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4490614373565b60405180910390fd5b6000861415612d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d88906144b3565b60405180910390fd5b848610612dd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dca90614253565b60405180910390fd5b6001841015612e17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0e90614453565b60405180910390fd5b60006002811115612e2457fe5b816002811115612e3057fe5b1415612e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e6890614273565b60405180910390fd5b848310612eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eaa906145b3565b60405180910390fd5b848210612ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eec90614233565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612f198a61280b565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612fe357fe5b021790555050505050505050505050565b606082471015613039576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161303090614353565b60405180910390fd5b613042856131d0565b613081576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613078906144f3565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516130ab91906140c6565b60006040518083038185875af1925050503d80600081146130e8576040519150601f19603f3d011682016040523d82523d6000602084013e6130ed565b606091505b50915091506130fd8282866131e3565b92505050949350505050565b606061316b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166127179092919063ffffffff16565b90506000815111156131cb578080602001905181019061318b9190613539565b6131ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131c1906145d3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b606083156131f357829050613243565b6000835111156132065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323a91906141d1565b60405180910390fd5b9392505050565b6000813590506132598161486a565b92915050565b60008151905061326e8161486a565b92915050565b600082601f83011261328557600080fd5b8151613298613293826146bf565b61468e565b915081818352602084019350602081019050838560208402820111156132bd57600080fd5b60005b838110156132ed57816132d3888261325f565b8452602084019350602083019250506001810190506132c0565b5050505092915050565b60008151905061330681614881565b92915050565b60008135905061331b81614898565b92915050565b600060c0828403121561333357600080fd5b81905092915050565b60008135905061334b816148a8565b92915050565b600081519050613360816148a8565b92915050565b60006020828403121561337857600080fd5b60006133868482850161324a565b91505092915050565b6000602082840312156133a157600080fd5b60006133af8482850161325f565b91505092915050565b60008060008060008060008060008060006101608c8e0312156133da57600080fd5b60006133e88e828f0161324a565b9b505060206133f98e828f0161324a565b9a5050604061340a8e828f0161324a565b995050606061341b8e828f0161324a565b985050608061342c8e828f0161333c565b97505060a061343d8e828f0161333c565b96505060c061344e8e828f0161333c565b95505060e061345f8e828f0161333c565b9450506101006134718e828f0161333c565b9350506101206134838e828f0161333c565b9250506101406134958e828f0161330c565b9150509295989b509295989b9093969950565b600080600061010084860312156134be57600080fd5b60006134cc8682870161324a565b93505060206134dd8682870161324a565b92505060406134ee86828701613321565b9150509250925092565b60006020828403121561350a57600080fd5b600082015167ffffffffffffffff81111561352457600080fd5b61353084828501613274565b91505092915050565b60006020828403121561354b57600080fd5b6000613559848285016132f7565b91505092915050565b60006020828403121561357457600080fd5b60006135828482850161333c565b91505092915050565b60006020828403121561359d57600080fd5b60006135ab84828501613351565b91505092915050565b6135bd8161471d565b82525050565b6135cc8161472f565b82525050565b6135db8161473b565b82525050565b60006135ec826146eb565b6135f68185614701565b9350613606818560208601614810565b80840191505092915050565b61361b816147a4565b82525050565b61362a816147c8565b82525050565b613639816147ec565b82525050565b613648816147fe565b82525050565b6000613659826146f6565b613663818561470c565b9350613673818560208601614810565b61367c81614845565b840191505092915050565b600061369460088361470c565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b60006136d4601b8361470c565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b600061371460228361470c565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061377a60158361470c565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b60006137ba601e8361470c565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006137fa60268361470c565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613860601b8361470c565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006138a0601c8361470c565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006138e060148361470c565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613920601f8361470c565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613960601e8361470c565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006139a060268361470c565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a06601d8361470c565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b6000613a46601a8361470c565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b6000613a8660118361470c565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b6000613ac660138361470c565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b6000613b06601a8361470c565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b6000613b4660158361470c565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613b8660298361470c565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bec601f8361470c565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b6000613c2c60218361470c565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c9260208361470c565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613cd260168361470c565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613d1260158361470c565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613d52601d8361470c565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613d9260248361470c565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df860138361470c565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613e3860198361470c565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613e7860178361470c565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613eb860058361470c565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613ef8602a8361470c565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613f5e602a8361470c565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fc4601e8361470c565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b600061400460148361470c565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000614044601a8361470c565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000614084600f8361470c565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b6140c08161479a565b82525050565b60006140d282846135e1565b915081905092915050565b60006020820190506140f260008301846135b4565b92915050565b600060408201905061410d60008301856135b4565b61411a602083018461363f565b9392505050565b600060408201905061413660008301856135b4565b61414360208301846140b7565b9392505050565b600060208201905061415f60008301846135c3565b92915050565b600060208201905061417a60008301846135d2565b92915050565b60006020820190506141956000830184613612565b92915050565b60006020820190506141b06000830184613621565b92915050565b60006020820190506141cb6000830184613630565b92915050565b600060208201905081810360008301526141eb818461364e565b905092915050565b6000602082019050818103600083015261420c81613687565b9050919050565b6000602082019050818103600083015261422c816136c7565b9050919050565b6000602082019050818103600083015261424c81613707565b9050919050565b6000602082019050818103600083015261426c8161376d565b9050919050565b6000602082019050818103600083015261428c816137ad565b9050919050565b600060208201905081810360008301526142ac816137ed565b9050919050565b600060208201905081810360008301526142cc81613853565b9050919050565b600060208201905081810360008301526142ec81613893565b9050919050565b6000602082019050818103600083015261430c816138d3565b9050919050565b6000602082019050818103600083015261432c81613913565b9050919050565b6000602082019050818103600083015261434c81613953565b9050919050565b6000602082019050818103600083015261436c81613993565b9050919050565b6000602082019050818103600083015261438c816139f9565b9050919050565b600060208201905081810360008301526143ac81613a39565b9050919050565b600060208201905081810360008301526143cc81613a79565b9050919050565b600060208201905081810360008301526143ec81613ab9565b9050919050565b6000602082019050818103600083015261440c81613af9565b9050919050565b6000602082019050818103600083015261442c81613b39565b9050919050565b6000602082019050818103600083015261444c81613b79565b9050919050565b6000602082019050818103600083015261446c81613bdf565b9050919050565b6000602082019050818103600083015261448c81613c1f565b9050919050565b600060208201905081810360008301526144ac81613c85565b9050919050565b600060208201905081810360008301526144cc81613cc5565b9050919050565b600060208201905081810360008301526144ec81613d05565b9050919050565b6000602082019050818103600083015261450c81613d45565b9050919050565b6000602082019050818103600083015261452c81613d85565b9050919050565b6000602082019050818103600083015261454c81613deb565b9050919050565b6000602082019050818103600083015261456c81613e2b565b9050919050565b6000602082019050818103600083015261458c81613e6b565b9050919050565b600060208201905081810360008301526145ac81613eab565b9050919050565b600060208201905081810360008301526145cc81613eeb565b9050919050565b600060208201905081810360008301526145ec81613f51565b9050919050565b6000602082019050818103600083015261460c81613fb7565b9050919050565b6000602082019050818103600083015261462c81613ff7565b9050919050565b6000602082019050818103600083015261464c81614037565b9050919050565b6000602082019050818103600083015261466c81614077565b9050919050565b600060208201905061468860008301846140b7565b92915050565b6000604051905081810181811067ffffffffffffffff821117156146b5576146b4614843565b5b8060405250919050565b600067ffffffffffffffff8211156146da576146d9614843565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006147288261477a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061477582614856565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006147af826147b6565b9050919050565b60006147c18261477a565b9050919050565b60006147d3826147da565b9050919050565b60006147e58261477a565b9050919050565b60006147f782614767565b9050919050565b60006148098261479a565b9050919050565b60005b8381101561482e578082015181840152602081019050614813565b8381111561483d576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061486757614866614843565b5b50565b6148738161471d565b811461487e57600080fd5b50565b61488a8161472f565b811461489557600080fd5b50565b600381106148a557600080fd5b50565b6148b18161479a565b81146148bc57600080fd5b5056fea2646970667358221220e7181b2ba4d1c3bb9e57d12c063690ecc18fa07966017865e716378e6ce1068c64736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102605760003560e01c80637bdf05af11610144578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610bc7578063e8dda6f514610bf0578063e97d87d514610c1b578063ebbab99214610c46578063f2fde38b14610c71578063fc0c546a14610c9a576102a0565b8063bc0163c114610af4578063bd896dcb14610b1f578063ce845d1d14610b48578063d0ebdbe714610b73578063d18e81b314610b9c576102a0565b80638da5cb5b116101085780638da5cb5b14610a0857806391f7cfb914610a33578063a4caeb4214610a5e578063b0d1818c14610a89578063b470aade14610ab2578063b6549f7514610add576102a0565b80637bdf05af1461095957806386d00e021461098457806386d1a69f146109af578063872a7810146109c65780638a5bdf5c146109f1576102a0565b806338af3eed116101dd578063481c6a75116101a1578063481c6a751461087f5780635051a5ec146108aa5780635b940081146108d557806360e7994414610900578063715018a61461091757806378e979251461092e576102a0565b806338af3eed146107a8578063392e53cd146107d3578063398057a3146107fe57806344b1231f1461082957806345d30a1714610854576102a0565b806320dc203d1161022457806320dc203d146106e75780632a627814146107105780632bc9ed02146107275780633197cbb61461075257806337aeb0861461077d576102a0565b8063029c6c9f14610624578063060406181461064f5780630b80f7771461067a5780630dff24d5146106915780630fb5a6b4146106bc576102a0565b366102a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610297906141f3565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610327906143d3565b60405180910390fd5b60003414610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036a90614213565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103f49190614165565b60206040518083038186803b15801561040c57600080fd5b505afa158015610420573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610444919061338f565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ad906144d3565b60405180910390fd5b60006104c0610cc5565b9050610511826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d77565b506001600281111561051f57fe5b603b60009054906101000a900460ff16600281111561053a57fe5b141561062057600061054a610cc5565b90508181101561058c5760006105698284610dc190919063ffffffff16565b905061058081603f54610e1190919063ffffffff16565b603f81905550506105d2565b60006105a18383610dc190919063ffffffff16565b9050603f548110156105c7576105c281603f54610dc190919063ffffffff16565b6105ca565b60005b603f81905550505b6105da610e66565b603f54111561061e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061590614433565b60405180910390fd5b505b5050005b34801561063057600080fd5b50610639610ed5565b6040516106469190614673565b60405180910390f35b34801561065b57600080fd5b50610664610ef3565b6040516106719190614673565b60405180910390f35b34801561068657600080fd5b5061068f610f2e565b005b34801561069d57600080fd5b506106a661109b565b6040516106b39190614673565b60405180910390f35b3480156106c857600080fd5b506106d16110e2565b6040516106de9190614673565b60405180910390f35b3480156106f357600080fd5b5061070e600480360381019061070991906134a8565b611100565b005b34801561071c57600080fd5b5061072561129b565b005b34801561073357600080fd5b5061073c611500565b604051610749919061414a565b60405180910390f35b34801561075e57600080fd5b50610767611513565b6040516107749190614673565b60405180910390f35b34801561078957600080fd5b50610792611519565b60405161079f9190614673565b60405180910390f35b3480156107b457600080fd5b506107bd61151f565b6040516107ca91906140dd565b60405180910390f35b3480156107df57600080fd5b506107e8611545565b6040516107f5919061414a565b60405180910390f35b34801561080a57600080fd5b50610813611558565b6040516108209190614673565b60405180910390f35b34801561083557600080fd5b5061083e610e66565b60405161084b9190614673565b60405180910390f35b34801561086057600080fd5b5061086961155e565b6040516108769190614673565b60405180910390f35b34801561088b57600080fd5b50610894611564565b6040516108a1919061419b565b60405180910390f35b3480156108b657600080fd5b506108bf61158a565b6040516108cc919061414a565b60405180910390f35b3480156108e157600080fd5b506108ea61159d565b6040516108f79190614673565b60405180910390f35b34801561090c57600080fd5b506109156116a8565b005b34801561092357600080fd5b5061092c6118ee565b005b34801561093a57600080fd5b50610943611a3a565b6040516109509190614673565b60405180910390f35b34801561096557600080fd5b5061096e611a40565b60405161097b9190614673565b60405180910390f35b34801561099057600080fd5b50610999611a7c565b6040516109a69190614673565b60405180910390f35b3480156109bb57600080fd5b506109c4611a82565b005b3480156109d257600080fd5b506109db611c5e565b6040516109e891906141b6565b60405180910390f35b3480156109fd57600080fd5b50610a06611c71565b005b348015610a1457600080fd5b50610a1d611d4a565b604051610a2a91906140dd565b60405180910390f35b348015610a3f57600080fd5b50610a48611d73565b604051610a559190614673565b60405180910390f35b348015610a6a57600080fd5b50610a73611dd1565b604051610a809190614673565b60405180910390f35b348015610a9557600080fd5b50610ab06004803603810190610aab9190613562565b611dd7565b005b348015610abe57600080fd5b50610ac7611fd6565b604051610ad49190614673565b60405180910390f35b348015610ae957600080fd5b50610af2611ff9565b005b348015610b0057600080fd5b50610b09612291565b604051610b169190614673565b60405180910390f35b348015610b2b57600080fd5b50610b466004803603810190610b4191906133b8565b6122c3565b005b348015610b5457600080fd5b50610b5d610cc5565b604051610b6a9190614673565b60405180910390f35b348015610b7f57600080fd5b50610b9a6004803603810190610b959190613366565b6122eb565b005b348015610ba857600080fd5b50610bb1612385565b604051610bbe9190614673565b60405180910390f35b348015610bd357600080fd5b50610bee6004803603810190610be99190613366565b61238d565b005b348015610bfc57600080fd5b50610c05612508565b604051610c129190614673565b60405180910390f35b348015610c2757600080fd5b50610c3061250e565b604051610c3d9190614673565b60405180910390f35b348015610c5257600080fd5b50610c5b612514565b604051610c689190614673565b60405180910390f35b348015610c7d57600080fd5b50610c986004803603810190610c939190613366565b612536565b005b348015610ca657600080fd5b50610caf6126f1565b604051610cbc9190614180565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d2291906140dd565b60206040518083038186803b158015610d3a57600080fd5b505afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d72919061358b565b905090565b6060610db983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612717565b905092915050565b600082821115610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90614333565b60405180910390fd5b818303905092915050565b600080828401905083811015610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e53906142b3565b60405180910390fd5b8091505092915050565b6000600280811115610e7457fe5b603b60009054906101000a900460ff166002811115610e8f57fe5b1415610e9f576035549050610ed2565b6000603a54118015610eb95750603a54610eb7612385565b105b15610ec75760009050610ed2565b610ecf611d73565b90505b90565b6000610eee60385460355461272f90919063ffffffff16565b905090565b6000610f296001610f1b610f05611fd6565b610f0d611a40565b61272f90919063ffffffff16565b610e1190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb390614493565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514611012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100990614313565b60405180910390fd5b61106d61101d611d4a565b611025610cc5565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b6000806110a6610cc5565b905060006110b2612291565b9050808211156110d8576110cf8183610dc190919063ffffffff16565b925050506110df565b6000925050505b90565b60006110fb603654603754610dc190919063ffffffff16565b905090565b603b60029054906101000a900460ff1615611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114790614533565b60405180910390fd5b6001603b60026101000a81548160ff0219169083151502179055506111868160200160208101906111819190613366565b61280b565b8060400160208101906111999190613366565b603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806060013560358190555080608001356036819055508060a0013560378190555060016038819055506001603b60036101000a81548160ff0219169083151502179055508060a001356039819055506002603b60006101000a81548160ff0219169083600281111561128857fe5b0217905550611296836128a9565b505050565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132290614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561139557600080fd5b505afa1580156113a9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113d291906134f8565b905060005b81518110156114d057603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061142a57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b8152600401611470929190614121565b602060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c29190613539565b5080806001019150506113d7565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156115ab57fe5b603b60009054906101000a900460ff1660028111156115c657fe5b14156115db576115d4612a27565b90506116a5565b60006039541180156115f557506039546115f3612385565b105b1561160357600090506116a5565b6001600281111561161057fe5b603b60009054906101000a900460ff16600281111561162b57fe5b14801561163a57506000603a54115b801561164e5750603a5461164c612385565b105b1561165c57600090506116a5565b600061168e603f54611680603c54611672611d73565b610dc190919063ffffffff16565b610dc190919063ffffffff16565b90506116a161169b610cc5565b82612ae1565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172f90614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906117df91906134f8565b905060005b81518110156118be57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061183757fe5b602002602001015160006040518363ffffffff1660e01b815260040161185e9291906140f8565b602060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b09190613539565b5080806001019150506117e4565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197390614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b600080611a4b612385565b90506036548111611a60576000915050611a79565b611a7560365482610dc190919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0990614593565b60405180910390fd5b6000611b1c61159d565b905060008111611b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b58906145f3565b60405180910390fd5b611b7681603c54610e1190919063ffffffff16565b603c81905550611beb603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611c539190614673565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890614593565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611d7e612385565b9050603654811015611d94576000915050611dce565b603754811115611da957603554915050611dce565b611dca611db4610ed5565b611dbc612514565b612afa90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5e90614593565b60405180910390fd5b60008111611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea190614413565b60405180910390fd5b80611eb361109b565b1015611ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eeb90614513565b60405180910390fd5b611f63603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611fcb9190614673565b60405180910390a250565b6000611ff4603854611fe66110e2565b61272f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614493565b60405180910390fd5b6001600281111561209457fe5b603b60009054906101000a900460ff1660028111156120af57fe5b146120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614553565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213c90614653565b60405180910390fd5b6000612163612152610e66565b603554610dc190919063ffffffff16565b9050600081116121a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219f906142d3565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061221e6121d5611d4a565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516122869190614673565b60405180910390a250565b60006122be603d546122b0603c54603554610dc190919063ffffffff16565b610dc190919063ffffffff16565b905090565b6122d58a8a8a8a8a8a8a8a8a8a612b6a565b6122de8b6128a9565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237090614493565b60405180910390fd5b612382816128a9565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461241d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161241490614593565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561248d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612484906143b3565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d816040516124fd91906140dd565b60405180910390a150565b603f5481565b60395481565b60006125316001612523610ef3565b610dc190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bb90614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262b90614293565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606127268484600085612ff4565b90509392505050565b6000808211612773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276a90614393565b60405180910390fd5b81838161277c57fe5b04905092915050565b6128068363a9059cbb60e01b84846040516024016127a4929190614121565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613109565b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291090614573565b60405180910390fd5b612922816131d0565b612961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612958906143f3565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b600080603954118015612a425750603954612a40612385565b105b15612a505760009050612ade565b60016002811115612a5d57fe5b603b60009054906101000a900460ff166002811115612a7857fe5b148015612a8757506000603a54115b8015612a9b5750603a54612a99612385565b105b15612aa95760009050612ade565b6000612ac7603c54612ab9611d73565b610dc190919063ffffffff16565b9050612ada612ad4610cc5565b82612ae1565b9150505b90565b6000818310612af05781612af2565b825b905092915050565b600080831415612b0d5760009050612b64565b6000828402905082848281612b1e57fe5b0414612b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5690614473565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff1615612bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb190614533565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c21906142f3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190614633565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0190614613565b60405180910390fd5b60008711612d4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4490614373565b60405180910390fd5b6000861415612d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d88906144b3565b60405180910390fd5b848610612dd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dca90614253565b60405180910390fd5b6001841015612e17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0e90614453565b60405180910390fd5b60006002811115612e2457fe5b816002811115612e3057fe5b1415612e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e6890614273565b60405180910390fd5b848310612eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eaa906145b3565b60405180910390fd5b848210612ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eec90614233565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612f198a61280b565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612fe357fe5b021790555050505050505050505050565b606082471015613039576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161303090614353565b60405180910390fd5b613042856131d0565b613081576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613078906144f3565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516130ab91906140c6565b60006040518083038185875af1925050503d80600081146130e8576040519150601f19603f3d011682016040523d82523d6000602084013e6130ed565b606091505b50915091506130fd8282866131e3565b92505050949350505050565b606061316b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166127179092919063ffffffff16565b90506000815111156131cb578080602001905181019061318b9190613539565b6131ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131c1906145d3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b606083156131f357829050613243565b6000835111156132065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323a91906141d1565b60405180910390fd5b9392505050565b6000813590506132598161486a565b92915050565b60008151905061326e8161486a565b92915050565b600082601f83011261328557600080fd5b8151613298613293826146bf565b61468e565b915081818352602084019350602081019050838560208402820111156132bd57600080fd5b60005b838110156132ed57816132d3888261325f565b8452602084019350602083019250506001810190506132c0565b5050505092915050565b60008151905061330681614881565b92915050565b60008135905061331b81614898565b92915050565b600060c0828403121561333357600080fd5b81905092915050565b60008135905061334b816148a8565b92915050565b600081519050613360816148a8565b92915050565b60006020828403121561337857600080fd5b60006133868482850161324a565b91505092915050565b6000602082840312156133a157600080fd5b60006133af8482850161325f565b91505092915050565b60008060008060008060008060008060006101608c8e0312156133da57600080fd5b60006133e88e828f0161324a565b9b505060206133f98e828f0161324a565b9a5050604061340a8e828f0161324a565b995050606061341b8e828f0161324a565b985050608061342c8e828f0161333c565b97505060a061343d8e828f0161333c565b96505060c061344e8e828f0161333c565b95505060e061345f8e828f0161333c565b9450506101006134718e828f0161333c565b9350506101206134838e828f0161333c565b9250506101406134958e828f0161330c565b9150509295989b509295989b9093969950565b600080600061010084860312156134be57600080fd5b60006134cc8682870161324a565b93505060206134dd8682870161324a565b92505060406134ee86828701613321565b9150509250925092565b60006020828403121561350a57600080fd5b600082015167ffffffffffffffff81111561352457600080fd5b61353084828501613274565b91505092915050565b60006020828403121561354b57600080fd5b6000613559848285016132f7565b91505092915050565b60006020828403121561357457600080fd5b60006135828482850161333c565b91505092915050565b60006020828403121561359d57600080fd5b60006135ab84828501613351565b91505092915050565b6135bd8161471d565b82525050565b6135cc8161472f565b82525050565b6135db8161473b565b82525050565b60006135ec826146eb565b6135f68185614701565b9350613606818560208601614810565b80840191505092915050565b61361b816147a4565b82525050565b61362a816147c8565b82525050565b613639816147ec565b82525050565b613648816147fe565b82525050565b6000613659826146f6565b613663818561470c565b9350613673818560208601614810565b61367c81614845565b840191505092915050565b600061369460088361470c565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b60006136d4601b8361470c565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b600061371460228361470c565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061377a60158361470c565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b60006137ba601e8361470c565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006137fa60268361470c565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613860601b8361470c565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006138a0601c8361470c565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006138e060148361470c565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613920601f8361470c565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613960601e8361470c565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006139a060268361470c565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a06601d8361470c565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b6000613a46601a8361470c565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b6000613a8660118361470c565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b6000613ac660138361470c565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b6000613b06601a8361470c565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b6000613b4660158361470c565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613b8660298361470c565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bec601f8361470c565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b6000613c2c60218361470c565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c9260208361470c565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613cd260168361470c565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613d1260158361470c565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613d52601d8361470c565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613d9260248361470c565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df860138361470c565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613e3860198361470c565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613e7860178361470c565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613eb860058361470c565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613ef8602a8361470c565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613f5e602a8361470c565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fc4601e8361470c565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b600061400460148361470c565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000614044601a8361470c565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000614084600f8361470c565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b6140c08161479a565b82525050565b60006140d282846135e1565b915081905092915050565b60006020820190506140f260008301846135b4565b92915050565b600060408201905061410d60008301856135b4565b61411a602083018461363f565b9392505050565b600060408201905061413660008301856135b4565b61414360208301846140b7565b9392505050565b600060208201905061415f60008301846135c3565b92915050565b600060208201905061417a60008301846135d2565b92915050565b60006020820190506141956000830184613612565b92915050565b60006020820190506141b06000830184613621565b92915050565b60006020820190506141cb6000830184613630565b92915050565b600060208201905081810360008301526141eb818461364e565b905092915050565b6000602082019050818103600083015261420c81613687565b9050919050565b6000602082019050818103600083015261422c816136c7565b9050919050565b6000602082019050818103600083015261424c81613707565b9050919050565b6000602082019050818103600083015261426c8161376d565b9050919050565b6000602082019050818103600083015261428c816137ad565b9050919050565b600060208201905081810360008301526142ac816137ed565b9050919050565b600060208201905081810360008301526142cc81613853565b9050919050565b600060208201905081810360008301526142ec81613893565b9050919050565b6000602082019050818103600083015261430c816138d3565b9050919050565b6000602082019050818103600083015261432c81613913565b9050919050565b6000602082019050818103600083015261434c81613953565b9050919050565b6000602082019050818103600083015261436c81613993565b9050919050565b6000602082019050818103600083015261438c816139f9565b9050919050565b600060208201905081810360008301526143ac81613a39565b9050919050565b600060208201905081810360008301526143cc81613a79565b9050919050565b600060208201905081810360008301526143ec81613ab9565b9050919050565b6000602082019050818103600083015261440c81613af9565b9050919050565b6000602082019050818103600083015261442c81613b39565b9050919050565b6000602082019050818103600083015261444c81613b79565b9050919050565b6000602082019050818103600083015261446c81613bdf565b9050919050565b6000602082019050818103600083015261448c81613c1f565b9050919050565b600060208201905081810360008301526144ac81613c85565b9050919050565b600060208201905081810360008301526144cc81613cc5565b9050919050565b600060208201905081810360008301526144ec81613d05565b9050919050565b6000602082019050818103600083015261450c81613d45565b9050919050565b6000602082019050818103600083015261452c81613d85565b9050919050565b6000602082019050818103600083015261454c81613deb565b9050919050565b6000602082019050818103600083015261456c81613e2b565b9050919050565b6000602082019050818103600083015261458c81613e6b565b9050919050565b600060208201905081810360008301526145ac81613eab565b9050919050565b600060208201905081810360008301526145cc81613eeb565b9050919050565b600060208201905081810360008301526145ec81613f51565b9050919050565b6000602082019050818103600083015261460c81613fb7565b9050919050565b6000602082019050818103600083015261462c81613ff7565b9050919050565b6000602082019050818103600083015261464c81614037565b9050919050565b6000602082019050818103600083015261466c81614077565b9050919050565b600060208201905061468860008301846140b7565b92915050565b6000604051905081810181811067ffffffffffffffff821117156146b5576146b4614843565b5b8060405250919050565b600067ffffffffffffffff8211156146da576146d9614843565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006147288261477a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061477582614856565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006147af826147b6565b9050919050565b60006147c18261477a565b9050919050565b60006147d3826147da565b9050919050565b60006147e58261477a565b9050919050565b60006147f782614767565b9050919050565b60006148098261479a565b9050919050565b60005b8381101561482e578082015181840152602081019050614813565b8381111561483d576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061486757614866614843565b5b50565b6148738161471d565b811461487e57600080fd5b50565b61488a8161472f565b811461489557600080fd5b50565b600381106148a557600080fd5b50565b6148b18161479a565b81146148bc57600080fd5b5056fea2646970667358221220e7181b2ba4d1c3bb9e57d12c063690ecc18fa07966017865e716378e6ce1068c64736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. This L2 variant includes a special initializer so that it can be created from a wallet's data received from L1. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1, so releasing surplus tokens might also only be possible by bridging tokens back to L1. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6797, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 6802, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 3244, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "51", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 3246, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "52", + "type": "t_address" + }, + { + "astId": 3248, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "53", + "type": "t_uint256" + }, + { + "astId": 3250, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "54", + "type": "t_uint256" + }, + { + "astId": 3252, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "55", + "type": "t_uint256" + }, + { + "astId": 3254, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 3256, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "57", + "type": "t_uint256" + }, + { + "astId": 3258, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "58", + "type": "t_uint256" + }, + { + "astId": 3260, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "59", + "type": "t_enum(Revocability)5096" + }, + { + "astId": 3262, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3264, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3266, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3268, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "60", + "type": "t_uint256" + }, + { + "astId": 3270, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "61", + "type": "t_uint256" + }, + { + "astId": 4692, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "62", + "type": "t_contract(IGraphTokenLockManager)5278" + }, + { + "astId": 4694, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "63", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)5278": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)5096": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-one/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json b/packages/token-distribution/deployments/arbitrum-one/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json new file mode 100644 index 000000000..4eda754ae --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-one/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json @@ -0,0 +1,152 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMathUpgradeable {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/arbitrum/ITokenGateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2020, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\ninterface ITokenGateway {\n /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated\n // event OutboundTransferInitiated(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized\n // event InboundTransferFinalized(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n function outboundTransfer(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n function finalizeInboundTransfer(\n address _token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n\n /**\n * @notice Calculate the address used when bridging an ERC20 token\n * @dev the L1 and L2 address oracles may not always be in sync.\n * For example, a custom token may have been registered but not deployed or the contract self destructed.\n * @param l1ERC20 address of L1 token\n * @return L2 address of a bridged ERC20 token\n */\n function calculateL2TokenAddress(address l1ERC20) external view returns (address);\n}\n" + }, + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n OwnableInitializable._initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 internal _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSelector(\n GraphTokenLockWallet.initialize.selector,\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(\n string[] calldata _signatures,\n address[] calldata _targets\n ) external override onlyOwner {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n *\n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n OwnableInitializable._initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) internal {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe because we are using the max uint256 value\n token.approve(dstList[i], type(uint256).max);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe cause we're using 0 as the amount\n token.approve(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n require(msg.value == 0, \"ETH transfers not supported\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n\n /**\n * @notice Receive function that always reverts.\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\n */\n receive() external payable {\n revert(\"Bad call\");\n }\n}\n" + }, + "contracts/ICallhookReceiver.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\n\n/**\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\n * be allowlisted by the governor, but also implement this interface that contains\n * the function that will actually be called by the L2GraphTokenGateway.\n */\npragma solidity ^0.7.3;\n\ninterface ICallhookReceiver {\n /**\n * @notice Receive tokens with a callhook from the bridge\n * @param _from Token sender in L1\n * @param _amount Amount of tokens that were transferred\n * @param _data ABI-encoded callhook data\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/L1GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { AddressUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { MinimalProxyFactory } from \"./MinimalProxyFactory.sol\";\nimport { IGraphTokenLock } from \"./IGraphTokenLock.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { SafeMathUpgradeable } from \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @title L1GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from GraphTokenLockWallets\n * to a counterpart on L2. It is deployed on L1 and will send the GRT through\n * the L1GraphTokenGateway with a callhook to the L2GraphTokenLockManager, including\n * data to create a L2GraphTokenLockWallet on L2.\n *\n * Note that the L2GraphTokenLockWallet will not allow releasing any GRT until the end of\n * the vesting timeline, but will allow sending the GRT back to the L1 wallet.\n *\n * Beneficiaries for a GraphTokenLockWallet can perform the depositToL2Locked call\n * as many times as they want, and the GRT will be sent to the same L2GraphTokenLockWallet.\n *\n * Since all retryable tickets to send transactions to L2 require ETH for gas, this\n * contract also allows users to deposit ETH to be used for gas on L2, both for\n * the depositToL2Locked calls and for the transfer tools in the Staking contract for\n * The Graph.\n *\n * See GIP-0046 for more details: https://forum.thegraph.com/t/4023\n */\ncontract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, MinimalProxyFactory {\n using SafeMathUpgradeable for uint256;\n\n /// Address of the L1 GRT token contract\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses\n address public immutable l2Implementation;\n /// Address of the L1GraphTokenGateway contract\n ITokenGateway public immutable l1Gateway;\n /// Address of the Staking contract, used to pull ETH for L2 ticket gas\n address payable public immutable staking;\n /// L2 lock manager for each L1 lock manager.\n /// L1 GraphTokenLockManager => L2GraphTokenLockManager\n mapping(address => address) public l2LockManager;\n /// L2 wallet owner for each L1 wallet owner.\n /// L1 wallet owner => L2 wallet owner\n mapping(address => address) public l2WalletOwner;\n /// L2 wallet address for each L1 wallet address.\n /// L1 wallet => L2 wallet\n mapping(address => address) public l2WalletAddress;\n /// ETH balance from each token lock, used to pay for L2 gas:\n /// L1 wallet address => ETH balance\n mapping(address => uint256) public tokenLockETHBalances;\n /// L2 beneficiary corresponding to each L1 wallet address.\n /// L1 wallet => L2 beneficiary\n mapping(address => address) public l2Beneficiary;\n /// Indicates whether an L2 wallet address for a wallet\n /// has been set manually, in which case it can't call depositToL2Locked.\n /// L1 wallet => bool\n mapping(address => bool) public l2WalletAddressSetManually;\n\n /// @dev Emitted when the L2 lock manager for an L1 lock manager is set\n event L2LockManagerSet(address indexed l1LockManager, address indexed l2LockManager);\n /// @dev Emitted when the L2 wallet owner for an L1 wallet owner is set\n event L2WalletOwnerSet(address indexed l1WalletOwner, address indexed l2WalletOwner);\n /// @dev Emitted when GRT is sent to L2 from a token lock\n event LockedFundsSentToL2(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l1LockManager,\n address l2LockManager,\n uint256 amount\n );\n /// @dev Emitted when an L2 wallet address is set for an L1 wallet\n event L2WalletAddressSet(address indexed l1Wallet, address indexed l2Wallet);\n /// @dev Emitted when ETH is deposited to a token lock's account\n event ETHDeposited(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when ETH is withdrawn from a token lock's account\n event ETHWithdrawn(address indexed tokenLock, address indexed destination, uint256 amount);\n /// @dev Emitted when ETH is pulled from a token lock's account by Staking or this tool to pay for an L2 ticket\n event ETHPulled(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when the L2 beneficiary for a partially vested L1 lock is set\n event L2BeneficiarySet(address indexed l1Wallet, address indexed l2Beneficiary);\n\n /**\n * @notice Construct a new L1GraphTokenLockTransferTool contract\n * @dev The deployer of the contract will become its owner.\n * Note this contract is meant to be deployed behind a transparent proxy,\n * so this will run at the implementation's storage context; it will set\n * immutable variables and make the implementation be owned by the deployer.\n * @param _graphToken Address of the L1 GRT token contract\n * @param _l2Implementation Address of the L2GraphTokenLockWallet implementation in L2\n * @param _l1Gateway Address of the L1GraphTokenGateway contract\n * @param _staking Address of the Staking contract\n */\n constructor(\n IERC20 _graphToken,\n address _l2Implementation,\n ITokenGateway _l1Gateway,\n address payable _staking\n ) initializer {\n OwnableInitializable._initialize(msg.sender);\n graphToken = _graphToken;\n l2Implementation = _l2Implementation;\n l1Gateway = _l1Gateway;\n staking = _staking;\n }\n\n /**\n * @notice Initialize the L1GraphTokenLockTransferTool contract\n * @dev This function will run in the proxy's storage context, so it will\n * set the owner of the proxy contract which can be different from the implementation owner.\n * @param _owner Address of the owner of the L1GraphTokenLockTransferTool contract\n */\n function initialize(address _owner) external initializer {\n OwnableInitializable._initialize(_owner);\n }\n\n /**\n * @notice Set the L2 lock manager that corresponds to an L1 lock manager\n * @param _l1LockManager Address of the L1 lock manager\n * @param _l2LockManager Address of the L2 lock manager (in L2)\n */\n function setL2LockManager(address _l1LockManager, address _l2LockManager) external onlyOwner {\n l2LockManager[_l1LockManager] = _l2LockManager;\n emit L2LockManagerSet(_l1LockManager, _l2LockManager);\n }\n\n /**\n * @notice Set the L2 wallet owner that corresponds to an L1 wallet owner\n * @param _l1WalletOwner Address of the L1 wallet owner\n * @param _l2WalletOwner Address of the L2 wallet owner (in L2)\n */\n function setL2WalletOwner(address _l1WalletOwner, address _l2WalletOwner) external onlyOwner {\n l2WalletOwner[_l1WalletOwner] = _l2WalletOwner;\n emit L2WalletOwnerSet(_l1WalletOwner, _l2WalletOwner);\n }\n\n /**\n * @notice Deposit ETH on a token lock's account, to be used for L2 retryable ticket gas.\n * This function can be called by anyone, but the ETH will be credited to the token lock.\n * DO NOT try to call this through the token lock, as locks do not forward ETH value (and the\n * function call should not be allowlisted).\n * @param _tokenLock Address of the L1 GraphTokenLockWallet that will own the ETH\n */\n function depositETH(address _tokenLock) external payable {\n tokenLockETHBalances[_tokenLock] = tokenLockETHBalances[_tokenLock].add(msg.value);\n emit ETHDeposited(_tokenLock, msg.value);\n }\n\n /**\n * @notice Withdraw ETH from a token lock's account.\n * This function must be called from the token lock contract, but the destination\n * _must_ be a different address, as any ETH sent to the token lock would otherwise be\n * lost.\n * @param _destination Address to send the ETH\n * @param _amount Amount of ETH to send\n */\n function withdrawETH(address _destination, uint256 _amount) external {\n require(_amount > 0, \"INVALID_AMOUNT\");\n // We can't send eth to a token lock or it will be stuck\n require(msg.sender != _destination, \"INVALID_DESTINATION\");\n require(tokenLockETHBalances[msg.sender] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[msg.sender] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = payable(_destination).call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHWithdrawn(msg.sender, _destination, _amount);\n }\n\n /**\n * @notice Pull ETH from a token lock's account, to be used for L2 retryable ticket gas.\n * This can only be called by the Staking contract.\n * @param _tokenLock GraphTokenLockWallet that owns the ETH that will be debited\n * @param _amount Amount of ETH to pull\n */\n function pullETH(address _tokenLock, uint256 _amount) external {\n require(msg.sender == staking, \"ONLY_STAKING\");\n require(tokenLockETHBalances[_tokenLock] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[_tokenLock] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = staking.call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHPulled(_tokenLock, _amount);\n }\n\n /**\n * @notice Deposit GRT to L2, from a token lock in L1 to a token lock in L2.\n * If the token lock in L2 does not exist, it will be created when the message is received\n * by the L2GraphTokenLockManager.\n * Before calling this (which must be done through the token lock wallet), make sure\n * there is enough ETH in the token lock's account to cover the L2 retryable ticket gas.\n * Note that L2 submission fee and gas refunds will be lost.\n * You can add ETH to the token lock's account by calling depositETH().\n * Note that after calling this, you will NOT be able to use setL2WalletAddressManually() to\n * set an L2 wallet address, as the L2 wallet address will be set automatically when the\n * message is received by the L2GraphTokenLockManager.\n * @dev The gas parameters for L2 can be estimated using the Arbitrum SDK.\n * @param _amount Amount of GRT to deposit\n * @param _l2Beneficiary Address of the beneficiary for the token lock in L2. Must be the same for subsequent calls of this function, and not an L1 contract.\n * @param _maxGas Maximum gas to use for the L2 retryable ticket\n * @param _gasPriceBid Gas price to use for the L2 retryable ticket\n * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket\n */\n function depositToL2Locked(\n uint256 _amount,\n address _l2Beneficiary,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n uint256 _maxSubmissionCost\n ) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n require(wallet.revocable() != IGraphTokenLock.Revocability.Enabled, \"REVOCABLE\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n if (l2Beneficiary[msg.sender] == address(0)) {\n require(_l2Beneficiary != address(0), \"INVALID_BENEFICIARY_ZERO\");\n require(!AddressUpgradeable.isContract(_l2Beneficiary), \"INVALID_BENEFICIARY_CONTRACT\");\n l2Beneficiary[msg.sender] = _l2Beneficiary;\n emit L2BeneficiarySet(msg.sender, _l2Beneficiary);\n } else {\n require(l2Beneficiary[msg.sender] == _l2Beneficiary, \"INVALID_BENEFICIARY\");\n }\n\n uint256 expectedEth = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(tokenLockETHBalances[msg.sender] >= expectedEth, \"INSUFFICIENT_ETH_BALANCE\");\n tokenLockETHBalances[msg.sender] -= expectedEth;\n\n bytes memory encodedData;\n {\n address l2Owner = l2WalletOwner[wallet.owner()];\n require(l2Owner != address(0), \"L2_OWNER_NOT_SET\");\n // Extract all the storage variables from the GraphTokenLockWallet\n L2GraphTokenLockManager.TransferredWalletData memory data = L2GraphTokenLockManager.TransferredWalletData({\n l1Address: msg.sender,\n owner: l2Owner,\n beneficiary: l2Beneficiary[msg.sender],\n managedAmount: wallet.managedAmount(),\n startTime: wallet.startTime(),\n endTime: wallet.endTime()\n });\n encodedData = abi.encode(data);\n }\n\n if (l2WalletAddress[msg.sender] == address(0)) {\n require(wallet.endTime() >= block.timestamp, \"FULLY_VESTED_USE_MANUAL_ADDRESS\");\n address newAddress = getDeploymentAddress(keccak256(encodedData), l2Implementation, l2Manager);\n l2WalletAddress[msg.sender] = newAddress;\n emit L2WalletAddressSet(msg.sender, newAddress);\n } else {\n require(!l2WalletAddressSetManually[msg.sender], \"CANT_DEPOSIT_TO_MANUAL_ADDRESS\");\n }\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n\n // Send the tokens with a message through the L1GraphTokenGateway to the L2GraphTokenLockManager\n graphToken.approve(address(l1Gateway), _amount);\n {\n bytes memory transferData = abi.encode(_maxSubmissionCost, encodedData);\n l1Gateway.outboundTransfer{ value: expectedEth }(\n address(graphToken),\n l2Manager,\n _amount,\n _maxGas,\n _gasPriceBid,\n transferData\n );\n }\n emit ETHPulled(msg.sender, expectedEth);\n emit LockedFundsSentToL2(msg.sender, l2WalletAddress[msg.sender], l1Manager, l2Manager, _amount);\n }\n\n /**\n * @notice Manually set the L2 wallet address for a token lock in L1.\n * This will only work for token locks that have not been initialized in L2 yet, and\n * that are fully vested (endTime < current timestamp).\n * This address can then be used to send stake or delegation to L2 on the Staking contract.\n * After calling this, the vesting lock will NOT be allowed to use depositToL2Locked\n * to send GRT to L2, the beneficiary must withdraw the tokens and bridge them manually.\n * @param _l2Wallet Address of the L2 wallet\n */\n function setL2WalletAddressManually(address _l2Wallet) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n\n // Check that the wallet is fully vested\n require(wallet.endTime() < block.timestamp, \"NOT_FULLY_VESTED\");\n\n // Check that the wallet has not set an L2 wallet yet\n require(l2WalletAddress[msg.sender] == address(0), \"L2_WALLET_ALREADY_SET\");\n\n // Check that the L2 address is not zero\n require(_l2Wallet != address(0), \"ZERO_ADDRESS\");\n // Set the L2 wallet address\n l2WalletAddress[msg.sender] = _l2Wallet;\n l2WalletAddressSetManually[msg.sender] = true;\n emit L2WalletAddressSet(msg.sender, _l2Wallet);\n }\n}\n" + }, + "contracts/L2GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { ICallhookReceiver } from \"./ICallhookReceiver.sol\";\nimport { GraphTokenLockManager } from \"./GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\n\n/**\n * @title L2GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\n * the L2GraphTokenLockTransferTool contract.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\n using SafeERC20 for IERC20;\n\n /// @dev Struct to hold the data of a transferred wallet; this is\n /// the data that must be encoded in L1 to send a wallet to L2.\n struct TransferredWalletData {\n address l1Address;\n address owner;\n address beneficiary;\n uint256 managedAmount;\n uint256 startTime;\n uint256 endTime;\n }\n\n /// Address of the L2GraphTokenGateway\n address public immutable l2Gateway;\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\n address public immutable l1TransferTool;\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\n /// L1 address => L2 address\n mapping(address => address) public l1WalletToL2Wallet;\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\n /// L2 address => L1 address\n mapping(address => address) public l2WalletToL1Wallet;\n\n /// @dev Event emitted when a wallet is received and created from L1\n event TokenLockCreatedFromL1(\n address indexed contractAddress,\n bytes32 initHash,\n address indexed beneficiary,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n address indexed l1Address\n );\n\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\n /// had already been received or not)\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\n\n /**\n * @dev Checks that the sender is the L2GraphTokenGateway.\n */\n modifier onlyL2Gateway() {\n require(msg.sender == l2Gateway, \"ONLY_GATEWAY\");\n _;\n }\n\n /**\n * @notice Constructor for the L2GraphTokenLockManager contract.\n * @param _graphToken Address of the L2 GRT token contract\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\n */\n constructor(\n IERC20 _graphToken,\n address _masterCopy,\n address _l2Gateway,\n address _l1TransferTool\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\n l2Gateway = _l2Gateway;\n l1TransferTool = _l1TransferTool;\n }\n\n /**\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\n * the existing wallet if it does.\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\n * @param _amount Amount of tokens received\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\n require(_from == l1TransferTool, \"ONLY_TRANSFER_TOOL\");\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\n\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\n // If the wallet was already received, just send the tokens to the L2 address\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\n } else {\n // Create contract using a minimal proxy and call initializer\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _amount);\n\n emit TokenLockCreatedFromL1(\n contractAddress,\n initHash,\n walletData.beneficiary,\n walletData.managedAmount,\n walletData.startTime,\n walletData.endTime,\n walletData.l1Address\n );\n }\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\n }\n\n /**\n * @dev Deploy a token lock wallet with data received from L1\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\n * @param _walletData Data of the wallet to be created\n * @return Hash of the initialization calldata\n * @return Address of the created contract\n */\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\n bytes memory initializer = _encodeInitializer(_walletData);\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\n return (keccak256(initializer), contractAddress);\n }\n\n /**\n * @dev Encode the initializer for the token lock wallet received from L1\n * @param _walletData Data of the wallet to be created\n * @return Encoded initializer calldata, including the function signature\n */\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\n return\n abi.encodeWithSelector(\n L2GraphTokenLockWallet.initializeFromL1.selector,\n address(this),\n address(_token),\n _walletData\n );\n }\n}\n" + }, + "contracts/L2GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\n\n/**\n * @title L2GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from L2 token lock wallets\n * back to their L1 counterparts.\n */\ncontract L2GraphTokenLockTransferTool {\n /// Address of the L2 GRT token\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenGateway\n ITokenGateway public immutable l2Gateway;\n /// Address of the L1 GRT token (in L1, no aliasing)\n address public immutable l1GraphToken;\n\n /// @dev Emitted when GRT is sent to L1 from a token lock\n event LockedFundsSentToL1(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l2LockManager,\n uint256 amount\n );\n\n /**\n * @notice Constructor for the L2GraphTokenLockTransferTool contract\n * @dev Note the L2GraphTokenLockTransferTool can be deployed behind a proxy,\n * and the constructor for the implementation will only set some immutable\n * variables.\n * @param _graphToken Address of the L2 GRT token\n * @param _l2Gateway Address of the L2GraphTokenGateway\n * @param _l1GraphToken Address of the L1 GRT token (in L1, no aliasing)\n */\n constructor(IERC20 _graphToken, ITokenGateway _l2Gateway, address _l1GraphToken) {\n graphToken = _graphToken;\n l2Gateway = _l2Gateway;\n l1GraphToken = _l1GraphToken;\n }\n\n /**\n * @notice Withdraw GRT from an L2 token lock wallet to its L1 counterpart.\n * This function must be called from an L2GraphTokenLockWallet contract.\n * The GRT will be sent to L1 and must be claimed using the Arbitrum Outbox on L1\n * after the standard Arbitrum withdrawal period (7 days).\n * @param _amount Amount of GRT to withdraw\n */\n function withdrawToL1Locked(uint256 _amount) external {\n L2GraphTokenLockWallet wallet = L2GraphTokenLockWallet(msg.sender);\n L2GraphTokenLockManager manager = L2GraphTokenLockManager(address(wallet.manager()));\n require(address(manager) != address(0), \"INVALID_SENDER\");\n address l1Wallet = manager.l2WalletToL1Wallet(msg.sender);\n require(l1Wallet != address(0), \"NOT_L1_WALLET\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n graphToken.approve(address(l2Gateway), _amount);\n\n // Send the tokens through the L2GraphTokenGateway to the L1 wallet counterpart\n l2Gateway.outboundTransfer(l1GraphToken, l1Wallet, _amount, 0, 0, \"\");\n emit LockedFundsSentToL1(l1Wallet, msg.sender, address(manager), _amount);\n }\n}\n" + }, + "contracts/L2GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\n\n/**\n * @title L2GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * This L2 variant includes a special initializer so that it can be created from\n * a wallet's data received from L1. These transferred wallets will not allow releasing\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\n *\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\n // Initializer when created from a message from L1\n function initializeFromL1(\n address _manager,\n address _token,\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\n ) external {\n require(!isInitialized, \"Already initialized\");\n isInitialized = true;\n\n OwnableInitializable._initialize(_walletData.owner);\n beneficiary = _walletData.beneficiary;\n token = IERC20(_token);\n\n managedAmount = _walletData.managedAmount;\n\n startTime = _walletData.startTime;\n endTime = _walletData.endTime;\n periods = 1;\n isAccepted = true;\n\n // Optionals\n releaseStartTime = _walletData.endTime;\n revocable = Revocability.Disabled;\n\n _setManager(_manager);\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { Create2 } from \"@openzeppelin/contracts/utils/Create2.sol\";\n\n/**\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n * Based on https://eips.ethereum.org/EIPS/eip-1167\n */\ncontract MinimalProxyFactory {\n /// @dev Emitted when a new proxy is created\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _deployer Address of the deployer that creates the contract\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation,\n address _deployer\n ) public pure returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\n }\n\n /**\n * @dev Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @dev Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n /// @dev Owner of the contract, can be retrieved with the public owner() function\n address private _owner;\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\n /// to allow adding variables here without breaking the proxy storage layout\n uint256[50] private __gap;\n\n /// @dev Emitted when ownership of the contract is transferred\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function _initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/tests/arbitrum/AddressAliasHelper.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/84e64dee6ee82adbf8ec34fd4b86c207a61d9007/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n l2Address = address(uint160(l1Address) + offset);\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n l1Address = address(uint160(l2Address) - offset);\n }\n}\n" + }, + "contracts/tests/arbitrum/IBridge.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IBridge {\n event MessageDelivered(\n uint256 indexed messageIndex,\n bytes32 indexed beforeInboxAcc,\n address inbox,\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n );\n\n event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);\n\n event InboxToggle(address indexed inbox, bool enabled);\n\n event OutboxToggle(address indexed outbox, bool enabled);\n\n function deliverMessageToInbox(\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n ) external payable returns (uint256);\n\n function executeCall(\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (bool success, bytes memory returnData);\n\n // These are only callable by the admin\n function setInbox(address inbox, bool enabled) external;\n\n function setOutbox(address inbox, bool enabled) external;\n\n // View functions\n\n function activeOutbox() external view returns (address);\n\n function allowedInboxes(address inbox) external view returns (bool);\n\n function allowedOutboxes(address outbox) external view returns (bool);\n\n function inboxAccs(uint256 index) external view returns (bytes32);\n\n function messageCount() external view returns (uint256);\n}\n" + }, + "contracts/tests/arbitrum/IInbox.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nimport \"./IBridge.sol\";\nimport \"./IMessageProvider.sol\";\n\ninterface IInbox is IMessageProvider {\n function sendL2Message(bytes calldata messageData) external returns (uint256);\n\n function sendUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendL1FundedUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function sendL1FundedContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function createRetryableTicket(\n address destAddr,\n uint256 arbTxCallValue,\n uint256 maxSubmissionCost,\n address submissionRefundAddress,\n address valueRefundAddress,\n uint256 maxGas,\n uint256 gasPriceBid,\n bytes calldata data\n ) external payable returns (uint256);\n\n function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);\n\n function bridge() external view returns (IBridge);\n\n function pauseCreateRetryables() external;\n\n function unpauseCreateRetryables() external;\n\n function startRewriteAddress() external;\n\n function stopRewriteAddress() external;\n}\n" + }, + "contracts/tests/arbitrum/IMessageProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IMessageProvider {\n event InboxMessageDelivered(uint256 indexed messageNum, bytes data);\n\n event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);\n}\n" + }, + "contracts/tests/BridgeMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IBridge.sol\";\n\n/**\n * @title Arbitrum Bridge mock contract\n * @dev This contract implements Arbitrum's IBridge interface for testing purposes\n */\ncontract BridgeMock is IBridge {\n /// Address of the (mock) Arbitrum Inbox\n address public inbox;\n /// Address of the (mock) Arbitrum Outbox\n address public outbox;\n /// Index of the next message on the inbox messages array\n uint256 public messageIndex;\n /// Inbox messages array\n bytes32[] public override inboxAccs;\n\n /**\n * @notice Deliver a message to the inbox. The encoded message will be\n * added to the inbox array, and messageIndex will be incremented.\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the message data\n * @return The next index for the inbox array\n */\n function deliverMessageToInbox(\n uint8 _kind,\n address _sender,\n bytes32 _messageDataHash\n ) external payable override returns (uint256) {\n messageIndex = messageIndex + 1;\n inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash)));\n emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash);\n return messageIndex;\n }\n\n /**\n * @notice Executes an L1 function call incoing from L2. This can only be called\n * by the Outbox.\n * @param _destAddr Contract to call\n * @param _amount ETH value to send\n * @param _data Calldata for the function call\n * @return True if the call was successful, false otherwise\n * @return Return data from the call\n */\n function executeCall(\n address _destAddr,\n uint256 _amount,\n bytes calldata _data\n ) external override returns (bool, bytes memory) {\n require(outbox == msg.sender, \"NOT_FROM_OUTBOX\");\n bool success;\n bytes memory returnData;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, returnData) = _destAddr.call{ value: _amount }(_data);\n emit BridgeCallTriggered(msg.sender, _destAddr, _amount, _data);\n return (success, returnData);\n }\n\n /**\n * @notice Set the address of the inbox. Anyone can call this, because it's a mock.\n * @param _inbox Address of the inbox\n * @param _enabled Enable the inbox (ignored)\n */\n function setInbox(address _inbox, bool _enabled) external override {\n inbox = _inbox;\n emit InboxToggle(inbox, _enabled);\n }\n\n /**\n * @notice Set the address of the outbox. Anyone can call this, because it's a mock.\n * @param _outbox Address of the outbox\n * @param _enabled Enable the outbox (ignored)\n */\n function setOutbox(address _outbox, bool _enabled) external override {\n outbox = _outbox;\n emit OutboxToggle(outbox, _enabled);\n }\n\n // View functions\n\n /**\n * @notice Getter for the active outbox (in this case there's only one)\n */\n function activeOutbox() external view override returns (address) {\n return outbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed inbox (in this case there's only one)\n * @param _inbox Address to check\n * @return True if the address is the allowed inbox, false otherwise\n */\n function allowedInboxes(address _inbox) external view override returns (bool) {\n return _inbox == inbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed outbox (in this case there's only one)\n * @param _outbox Address to check\n * @return True if the address is the allowed outbox, false otherwise\n */\n function allowedOutboxes(address _outbox) external view override returns (bool) {\n return _outbox == outbox;\n }\n\n /**\n * @notice Getter for the count of messages in the inboxAccs\n * @return Number of messages in inboxAccs\n */\n function messageCount() external view override returns (uint256) {\n return inboxAccs.length;\n }\n}\n" + }, + "contracts/tests/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock contract.\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @notice Contract Constructor.\n * @param _initialSupply Initial supply\n * @param _mintTo Address to whitch to mint the initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n\n /**\n * @notice Mint tokens to an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _to Address to mint tokens to\n * @param _amount Amount of tokens to mint\n */\n function bridgeMint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n\n /**\n * @notice Burn tokens from an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _from Address to burn tokens from\n * @param _amount Amount of tokens to burn\n */\n function bridgeBurn(address _from, uint256 _amount) external {\n _burn(_from, _amount);\n }\n}\n" + }, + "contracts/tests/InboxMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IInbox.sol\";\nimport \"./arbitrum/AddressAliasHelper.sol\";\n\n/**\n * @title Arbitrum Inbox mock contract\n * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes\n */\ncontract InboxMock is IInbox {\n /// @dev Type indicator for a standard L2 message\n uint8 internal constant L2_MSG = 3;\n /// @dev Type indicator for a retryable ticket message\n // solhint-disable-next-line const-name-snakecase\n uint8 internal constant L1MessageType_submitRetryableTx = 9;\n /// Address of the Bridge (mock) contract\n IBridge public override bridge;\n\n /**\n * @notice Send a message to L2 (by delivering it to the Bridge)\n * @param _messageData Encoded data to send in the message\n * @return Message number returned by the inbox\n */\n function sendL2Message(bytes calldata _messageData) external override returns (uint256) {\n uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @notice Set the address of the (mock) bridge\n * @param _bridge Address of the bridge\n */\n function setBridge(address _bridge) external {\n bridge = IBridge(_bridge);\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendContractTransaction(\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedContractTransaction(\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Creates a retryable ticket for an L2 transaction\n * @param _destAddr Address of the contract to call in L2\n * @param _arbTxCallValue Callvalue to use in the L2 transaction\n * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei\n * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost\n * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled\n * @param _maxGas Max gas for the L2 transcation\n * @param _gasPriceBid Gas price bid on L2\n * @param _data Encoded calldata for the L2 transaction (including function selector)\n * @return Message number returned by the bridge\n */\n function createRetryableTicket(\n address _destAddr,\n uint256 _arbTxCallValue,\n uint256 _maxSubmissionCost,\n address _submissionRefundAddress,\n address _valueRefundAddress,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable override returns (uint256) {\n _submissionRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_submissionRefundAddress);\n _valueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_valueRefundAddress);\n return\n _deliverMessage(\n L1MessageType_submitRetryableTx,\n msg.sender,\n abi.encodePacked(\n uint256(uint160(bytes20(_destAddr))),\n _arbTxCallValue,\n msg.value,\n _maxSubmissionCost,\n uint256(uint160(bytes20(_submissionRefundAddress))),\n uint256(uint160(bytes20(_valueRefundAddress))),\n _maxGas,\n _gasPriceBid,\n _data.length,\n _data\n )\n );\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function depositEth(uint256) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function pauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function unpauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function startRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function stopRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageData Encoded message data\n * @return Message number returned by the bridge\n */\n function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) {\n uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the encoded message data\n * @return Message number returned by the bridge\n */\n function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) {\n return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash);\n }\n}\n" + }, + "contracts/tests/L1TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\n\n/**\n * @title L1 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L1TokenGatewayMock is Ownable {\n using SafeMath for uint256;\n /// Next sequence number to return when outboundTransfer is called\n uint256 public nextSeqNum;\n\n /// @dev Emitted when a (fake) retryable ticket is created\n event FakeTxToL2(\n address from,\n uint256 value,\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 maxSubmissionCost,\n bytes outboundCalldata\n );\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2\n event DepositInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L1 Token Gateway Contract Constructor.\n */\n constructor() {}\n\n /**\n * @notice Creates and sends a fake retryable ticket to transfer GRT to L2.\n * This mock will actually just emit an event with parameters equivalent to what the real L1GraphTokenGateway\n * would send to L2.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _maxGas Gas limit for L2 execution of the ticket\n * @param _gasPriceBid Price per gas on L2\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return Sequence number of the retryable ticket created by Inbox (always )\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 seqNum = nextSeqNum;\n nextSeqNum += 1;\n {\n uint256 maxSubmissionCost;\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, maxSubmissionCost, extraData) = _parseOutboundData(_data);\n require(maxSubmissionCost > 0, \"NO_SUBMISSION_COST\");\n\n {\n // makes sure only sufficient ETH is supplied as required for successful redemption on L2\n // if a user does not desire immediate redemption they should provide\n // a msg.value of AT LEAST maxSubmissionCost\n uint256 expectedEth = maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(msg.value >= expectedEth, \"WRONG_ETH_VALUE\");\n }\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // transfer tokens to escrow\n IERC20(_l1Token).transferFrom(from, address(this), _amount);\n\n emit FakeTxToL2(from, msg.value, _maxGas, _gasPriceBid, maxSubmissionCost, outboundCalldata);\n }\n }\n emit DepositInitiated(_l1Token, from, _to, seqNum, _amount);\n\n return abi.encode(seqNum);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L2\n * Actually does nothing, just keeping it here as its useful to define the expected\n * calldata for the outgoing transfer in tests.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recepient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {}\n\n /**\n * @notice Creates calldata required to create a retryable ticket\n * @dev encodes the target function with its params which\n * will be called on L2 when the retryable ticket is redeemed\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L1 from which we're transferring tokens\n * @param _to Address on L2 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L2 transaction, which must be empty unless the caller is whitelisted\n * @return Encoded calldata (including function selector) for the L2 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n bytes memory emptyBytes;\n\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(emptyBytes, _data)\n );\n }\n\n /**\n * @notice Decodes calldata required for transfer of tokens to L2\n * @dev Data must include maxSubmissionCost, extraData can be left empty. When the router\n * sends an outbound message, data also contains the from address, but this mock\n * doesn't consider this case\n * @param _data Encoded callhook data containing maxSubmissionCost and extraData\n * @return Sender of the tx\n * @return Max ether value used to submit the retryable ticket\n * @return Additional data sent to L2\n */\n function _parseOutboundData(bytes memory _data) private view returns (address, uint256, bytes memory) {\n address from;\n uint256 maxSubmissionCost;\n bytes memory extraData;\n from = msg.sender;\n // User-encoded data contains the max retryable ticket submission cost\n // and additional L2 calldata\n (maxSubmissionCost, extraData) = abi.decode(_data, (uint256, bytes));\n return (from, maxSubmissionCost, extraData);\n }\n}\n" + }, + "contracts/tests/L2TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\nimport { GraphTokenMock } from \"./GraphTokenMock.sol\";\nimport { ICallhookReceiver } from \"../ICallhookReceiver.sol\";\n\n/**\n * @title L2 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L2TokenGatewayMock is Ownable {\n /// Address of the L1 GRT contract\n address public immutable l1Token;\n /// Address of the L2 GRT contract\n address public immutable l2Token;\n /// Next ID to return when sending an outboundTransfer\n uint256 public nextId;\n\n /// @dev Emitted when a (fake) transaction to L1 is created\n event FakeTxToL1(address from, bytes outboundCalldata);\n /// @dev Emitted when a (fake) retryable ticket is received from L1\n event DepositFinalized(address token, address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are withdrawn to L1 from L2\n event WithdrawalInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L2 Token Gateway Contract Constructor.\n * @param _l1Token Address of the L1 GRT contract\n * @param _l2Token Address of the L2 GRT contract\n */\n constructor(address _l1Token, address _l2Token) {\n l1Token = _l1Token;\n l2Token = _l2Token;\n }\n\n /**\n * @notice Creates and sends a (fake) transfer of GRT to L1.\n * This mock will actually just emit an event with parameters equivalent to what the real L2GraphTokenGateway\n * would send to L1.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return ID of the L2-L1 message (incrementing on every call)\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_l1Token == l1Token, \"INVALID_L1_TOKEN\");\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 id = nextId;\n nextId += 1;\n {\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, extraData) = _parseOutboundData(_data);\n\n require(msg.value == 0, \"!value\");\n require(extraData.length == 0, \"!extraData\");\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // burn tokens from the sender, they will be released from escrow in L1\n GraphTokenMock(l2Token).bridgeBurn(from, _amount);\n\n emit FakeTxToL1(from, outboundCalldata);\n }\n }\n emit WithdrawalInitiated(_l1Token, from, _to, id, _amount);\n\n return abi.encode(id);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L1\n * Implements calling callhooks if data is non-empty.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recipient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata, will trigger an onTokenTransfer call if non-empty\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {\n require(_l1Token == l1Token, \"TOKEN_NOT_GRT\");\n require(msg.value == 0, \"INVALID_NONZERO_VALUE\");\n\n GraphTokenMock(l2Token).bridgeMint(_to, _amount);\n\n if (_data.length > 0) {\n ICallhookReceiver(_to).onTokenTransfer(_from, _amount, _data);\n }\n\n emit DepositFinalized(_l1Token, _from, _to, _amount);\n }\n\n /**\n * @notice Calculate the L2 address of a bridged token\n * @dev In our case, this would only work for GRT.\n * @param l1ERC20 address of L1 GRT contract\n * @return L2 address of the bridged GRT token\n */\n function calculateL2TokenAddress(address l1ERC20) public view returns (address) {\n if (l1ERC20 != l1Token) {\n return address(0);\n }\n return l2Token;\n }\n\n /**\n * @notice Creates calldata required to create a tx to L1\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L2 from which we're transferring tokens\n * @param _to Address on L1 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L1 transaction, which must be empty\n * @return Encoded calldata (including function selector) for the L1 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(0, _data)\n );\n }\n\n /**\n * @dev Decodes calldata required for transfer of tokens to L1.\n * extraData can be left empty\n * @param _data Encoded callhook data\n * @return Sender of the tx\n * @return Any other data sent to L1\n */\n function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {\n address from;\n bytes memory extraData;\n // The mock doesn't take messages from the Router\n from = msg.sender;\n extraData = _data;\n return (from, extraData);\n }\n}\n" + }, + "contracts/tests/Stakes.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(\n Stakes.Indexer memory stake,\n uint256 _delegatedCapacity\n ) internal pure returns (uint256) {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "contracts/tests/StakingMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n receive() external payable {}\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/tests/WalletMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title WalletMock: a mock wallet contract for testing purposes\n * @dev For testing only, DO NOT USE IN PRODUCTION.\n * This is used to test L1-L2 transfer tools and to create scenarios\n * where an invalid wallet calls the transfer tool, e.g. a wallet that has an invalid\n * manager, or a wallet that has not been initialized.\n */\ncontract WalletMock {\n /// Target contract for the fallback function (usually a transfer tool contract)\n address public immutable target;\n /// Address of the GRT (mock) token\n address public immutable token;\n /// Address of the wallet's manager\n address public immutable manager;\n /// Whether the wallet has been initialized\n bool public immutable isInitialized;\n /// Whether the beneficiary has accepted the lock\n bool public immutable isAccepted;\n\n /**\n * @notice WalletMock constructor\n * @dev This constructor sets all the state variables so that\n * specific test scenarios can be created just by deploying this contract.\n * @param _target Target contract for the fallback function\n * @param _token Address of the GRT (mock) token\n * @param _manager Address of the wallet's manager\n * @param _isInitialized Whether the wallet has been initialized\n * @param _isAccepted Whether the beneficiary has accepted the lock\n */\n constructor(address _target, address _token, address _manager, bool _isInitialized, bool _isAccepted) {\n target = _target;\n token = _token;\n manager = _manager;\n isInitialized = _isInitialized;\n isAccepted = _isAccepted;\n }\n\n /**\n * @notice Fallback function\n * @dev This function calls the target contract with the data sent to this contract.\n * This is used to test the L1-L2 transfer tool.\n */\n fallback() external payable {\n // Call function with data\n Address.functionCall(target, msg.data);\n }\n\n /**\n * @notice Receive function\n * @dev This function is added to avoid compiler warnings, but just reverts.\n */\n receive() external payable {\n revert(\"Invalid call\");\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-sepolia/.chainId b/packages/token-distribution/deployments/arbitrum-sepolia/.chainId new file mode 100644 index 000000000..71ba4d632 --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-sepolia/.chainId @@ -0,0 +1 @@ +421614 \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockManager.json b/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockManager.json new file mode 100644 index 000000000..c0a2d0689 --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockManager.json @@ -0,0 +1,1198 @@ +{ + "address": "0x63E25D0319970253B003464b4008A8238B6FC02c", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1TransferTool", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Address", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedTokensReceivedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1Address", + "type": "address" + } + ], + "name": "TokenLockCreatedFromL1", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1TransferTool", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l1WalletToL2Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletToL1Wallet", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onTokenTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x898911d0d648301e5f07e9a17e2f615dc4e9fd02a233bf0a10a46ccbdb052119", + "receipt": { + "to": null, + "from": "0xadE6B8EB69a49B56929C1d4F4b428d791861dB6f", + "contractAddress": "0x63E25D0319970253B003464b4008A8238B6FC02c", + "transactionIndex": 1, + "gasUsed": "3879837", + "logsBloom": "0x00000000000000000000000000000000000004000000000000800000000000000000000000020004000000000000000000000000000000000000000000002000000000000000000000000000000000200001000000000000000000400000000000000000028000000001000000000800010000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000200000000000000000000000000", + "blockHash": "0x6792d699b56a62528ab4fe1f2bf96bf061087ddbc7f786a30a253b7e46bf0eee", + "transactionHash": "0x898911d0d648301e5f07e9a17e2f615dc4e9fd02a233bf0a10a46ccbdb052119", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 675027, + "transactionHash": "0x898911d0d648301e5f07e9a17e2f615dc4e9fd02a233bf0a10a46ccbdb052119", + "address": "0x63E25D0319970253B003464b4008A8238B6FC02c", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000ade6b8eb69a49b56929c1d4f4b428d791861db6f" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x6792d699b56a62528ab4fe1f2bf96bf061087ddbc7f786a30a253b7e46bf0eee" + }, + { + "transactionIndex": 1, + "blockNumber": 675027, + "transactionHash": "0x898911d0d648301e5f07e9a17e2f615dc4e9fd02a233bf0a10a46ccbdb052119", + "address": "0x63E25D0319970253B003464b4008A8238B6FC02c", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x00000000000000000000000045ffa6dad9f49c5018e5345eadf6e2e5c7116f64" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x6792d699b56a62528ab4fe1f2bf96bf061087ddbc7f786a30a253b7e46bf0eee" + } + ], + "blockNumber": 675027, + "cumulativeGasUsed": "3879837", + "status": 1, + "byzantium": true + }, + "args": [ + "0xf8c05dCF59E8B28BFD5eed176C562bEbcfc7Ac04", + "0x45FfA6DaD9F49C5018E5345eAdf6E2e5C7116F64", + "0xB24Ce0f8c18c4DdDa584A7EeC132F49C966813bb", + "0x543F8BFFb65c46091B4eEF4b1c394dFa43C4b065" + ], + "solcInputHash": "095bd30babc75057be19228ca1fd7aa4", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l2Gateway\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_l1TransferTool\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l2Address\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"LockedTokensReceivedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"}],\"name\":\"TokenLockCreatedFromL1\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l1TransferTool\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l1WalletToL2Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"l2Gateway\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"l2WalletToL1Wallet\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"LockedTokensReceivedFromL1(address,address,uint256)\":{\"details\":\"Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)\"},\"TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)\":{\"details\":\"Event emitted when a wallet is received and created from L1\"}},\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Address of the L2 GRT token contract\",\"_l1TransferTool\":\"Address of the L1 transfer tool contract (in L1, without aliasing)\",\"_l2Gateway\":\"Address of the L2GraphTokenGateway contract\",\"_masterCopy\":\"Address of the master copy of the L2GraphTokenLockWallet implementation\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address)\":{\"details\":\"Uses address(this) as deployer to compute the address. Only for backwards compatibility.\",\"params\":{\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"onTokenTransfer(address,uint256,bytes)\":{\"details\":\"This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.\",\"params\":{\"_amount\":\"Amount of tokens received\",\"_data\":\"Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\",\"_from\":\"Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor for the L2GraphTokenLockManager contract.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"l1TransferTool()\":{\"notice\":\"Address of the L1 transfer tool contract (in L1, no aliasing)\"},\"l1WalletToL2Wallet(address)\":{\"notice\":\"Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address\"},\"l2Gateway()\":{\"notice\":\"Address of the L2GraphTokenGateway\"},\"l2WalletToL1Wallet(address)\":{\"notice\":\"Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address\"},\"onTokenTransfer(address,uint256,bytes)\":{\"notice\":\"This function is called by the L2GraphTokenGateway when tokens are sent from L1.\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockManager.sol\":\"L2GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @dev Uses address(this) as deployer to compute the address. Only for backwards compatibility.\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation\\n ) public view returns (address) {\\n return getDeploymentAddress(_salt, _implementation, address(this));\\n }\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0xc0ad119f676fe82b234fd5c830d9bc443e9038c0cfe5dc4de3a3bf621d3f69df\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b5060405162004a3538038062004a35833981810160405281019062000037919062000410565b838360006200004b6200022860201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001539062000586565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ae816200023060201b60201c565b50508173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1660601b815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1660601b815250505050505062000635565b600033905090565b620002406200022860201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1662000266620003b960201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1614620002bf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b69062000564565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141562000332576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003299062000542565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600081519050620003f38162000601565b92915050565b6000815190506200040a816200061b565b92915050565b600080600080608085870312156200042757600080fd5b60006200043787828801620003f9565b94505060206200044a87828801620003e2565b93505060406200045d87828801620003e2565b92505060606200047087828801620003e2565b91505092959194509250565b60006200048b601983620005a8565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000620004cd602083620005a8565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200050f601483620005a8565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b600060208201905081810360008301526200055d816200047c565b9050919050565b600060208201905081810360008301526200057f81620004be565b9050919050565b60006020820190508181036000830152620005a18162000500565b9050919050565b600082825260208201905092915050565b6000620005c682620005e1565b9050919050565b6000620005da82620005b9565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200060c81620005b9565b81146200061857600080fd5b50565b6200062681620005cd565b81146200063257600080fd5b50565b60805160601c60a05160601c6143cc620006696000398061096452806112cb525080611014528061123d52506143cc6000f3fe608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063b6b55f2511610097578063cf497e6c11610071578063cf497e6c1461047f578063f1d24c451461049b578063f2fde38b146104cb578063fc0c546a146104e75761018e565b8063b6b55f2514610417578063bdb62fbe14610433578063c1ab13db146104635761018e565b80638da5cb5b146103675780638fa74a0e146103855780639c05fc60146103a3578063a3457466146103bf578063a4c0ed36146103dd578063a619486e146103f95761018e565b8063463013a21161014b57806368d30c2e1161012557806368d30c2e146102e15780636e03b8dc146102fd578063715018a61461032d57806379ee1bdf146103375761018e565b8063463013a21461028b578063586a5353146102a75780635975e00c146102c55761018e565b806303990a6c14610193578063045b7fe2146101af5780630602ba2b146101df5780630cd6178f1461020f5780632e1a7d4d1461023f57806343fb93d91461025b575b600080fd5b6101ad60048036038101906101a89190612faf565b610505565b005b6101c960048036038101906101c49190612d02565b6106ad565b6040516101d69190613a58565b60405180910390f35b6101f960048036038101906101f49190612f86565b6106e0565b6040516102069190613c56565b60405180910390f35b61022960048036038101906102249190612d02565b610721565b6040516102369190613a58565b60405180910390f35b61025960048036038101906102549190613075565b610754565b005b61027560048036038101906102709190612f37565b6108b1565b6040516102829190613a58565b60405180910390f35b6102a560048036038101906102a09190612ff4565b6108d6565b005b6102af610962565b6040516102bc9190613a58565b60405180910390f35b6102df60048036038101906102da9190612d02565b610986565b005b6102fb60048036038101906102f69190612d2b565b610b17565b005b61031760048036038101906103129190612f86565b610e5f565b6040516103249190613a58565b60405180910390f35b610335610e92565b005b610351600480360381019061034c9190612d02565b610fcc565b60405161035e9190613c56565b60405180910390f35b61036f610fe9565b60405161037c9190613a58565b60405180910390f35b61038d611012565b60405161039a9190613a58565b60405180910390f35b6103bd60048036038101906103b89190612e5d565b611036565b005b6103c7611163565b6040516103d49190613c34565b60405180910390f35b6103f760048036038101906103f29190612df1565b61123b565b005b6104016117a1565b60405161040e9190613a58565b60405180910390f35b610431600480360381019061042c9190613075565b6117c7565b005b61044d60048036038101906104489190612efb565b6118aa565b60405161045a9190613a58565b60405180910390f35b61047d60048036038101906104789190612d02565b6118bf565b005b61049960048036038101906104949190612d02565b6119e0565b005b6104b560048036038101906104b09190612f86565b611b53565b6040516104c29190613a58565b60405180910390f35b6104e560048036038101906104e09190612d02565b611bce565b005b6104ef611d77565b6040516104fc9190613cb6565b60405180910390f35b61050d611da1565b73ffffffffffffffffffffffffffffffffffffffff1661052b610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610581576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161057890613ed7565b60405180910390fd5b600061058d8383611da9565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c986866040516106a0929190613cd1565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff1661070283611b53565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61075c611da1565b73ffffffffffffffffffffffffffffffffffffffff1661077a610fe9565b73ffffffffffffffffffffffffffffffffffffffff16146107d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107c790613ed7565b60405180910390fd5b60008111610813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080a90613eb7565b60405180910390fd5b6108603382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516108a69190613fb7565b60405180910390a250565b60006108cd846108c085611ebd565b8051906020012084611f33565b90509392505050565b6108de611da1565b73ffffffffffffffffffffffffffffffffffffffff166108fc610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094990613ed7565b60405180910390fd5b61095d838383611f77565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b61098e611da1565b73ffffffffffffffffffffffffffffffffffffffff166109ac610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610a02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f990613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6990613d97565b60405180910390fd5b610a8681600261215990919063ffffffff16565b610ac5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610abc90613f17565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610b0c9190613c56565b60405180910390a250565b610b1f611da1565b73ffffffffffffffffffffffffffffffffffffffff16610b3d610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610b93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8a90613ed7565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610bef9190613a58565b60206040518083038186803b158015610c0757600080fd5b505afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f919061309e565b1015610c80576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7790613dd7565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610cd19b9a99989796959493929190613a73565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d668280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612189565b9050610db5818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610e4a989796959493929190613bb6565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e9a611da1565b73ffffffffffffffffffffffffffffffffffffffff16610eb8610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610f0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0590613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610fe282600261220590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b61103e611da1565b73ffffffffffffffffffffffffffffffffffffffff1661105c610fe9565b73ffffffffffffffffffffffffffffffffffffffff16146110b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a990613ed7565b60405180910390fd5b8181905084849050146110fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f190613d57565b60405180910390fd5b60005b8484905081101561115c5761114f85858381811061111757fe5b90506020028101906111299190613fd2565b85858581811061113557fe5b905060200201602081019061114a9190612d02565b611f77565b80806001019150506110fd565b5050505050565b6060806111706002612235565b67ffffffffffffffff8111801561118657600080fd5b506040519080825280602002602001820160405280156111b55781602001602082028036833780820191505090505b50905060005b6111c56002612235565b811015611233576111e081600261224a90919063ffffffff16565b8282815181106111ec57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506111bb565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c090613d77565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611357576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134e90613e17565b60405180910390fd5b61135f612a33565b828281019061136e919061304c565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114bc576114b760066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b6116ce565b6000806114e085856040516114d2929190613a0f565b604051809103902084612264565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506116358187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116c39493929190613c71565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117929190613fb7565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161180a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180190613eb7565b60405180910390fd5b611859333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166122bb909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e8260405161189f9190613fb7565b60405180910390a250565b60006118b78383306108b1565b905092915050565b6118c7611da1565b73ffffffffffffffffffffffffffffffffffffffff166118e5610fe9565b73ffffffffffffffffffffffffffffffffffffffff161461193b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193290613ed7565b60405180910390fd5b61194f81600261234490919063ffffffff16565b61198e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161198590613e37565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119d59190613c56565b60405180910390a250565b6119e8611da1565b73ffffffffffffffffffffffffffffffffffffffff16611a06610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614611a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5390613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611acc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac390613e57565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611bd6611da1565b73ffffffffffffffffffffffffffffffffffffffff16611bf4610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614611c4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4190613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611cba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb190613db7565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611e2f83836040516024016040516020818303038152906040529190604051611dd5929190613a3f565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612374565b905092915050565b611eb88363a9059cbb60e01b8484604051602401611e56929190613b8d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506123cc565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611f199493929190613973565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611f5194939291906139c1565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611fe6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fdd90613e77565b60405180910390fd5b611fef81612493565b61202e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202590613f97565b60405180910390fd5b600061203a8484611da9565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9878760405161214b929190613cd1565b60405180910390a450505050565b6000612181836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6124a6565b905092915050565b6000806121a060008661219b87611ebd565b612516565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156121fa576121f88184612627565b505b809150509392505050565b600061222d836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612671565b905092915050565b600061224382600001612694565b9050919050565b600061225983600001836126a5565b60001c905092915050565b600080606061227284612712565b905060006122a386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612189565b90508180519060200120819350935050509250929050565b61233e846323b872dd60e01b8585856040516024016122dc93929190613b56565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506123cc565b50505050565b600061236c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6127b7565b905092915050565b600060048251146123ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b190613ef7565b60405180910390fd5b60006020830151905080915050919050565b606061242e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661289f9092919063ffffffff16565b905060008151111561248e578080602001905181019061244e9190612ed2565b61248d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248490613f57565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124b28383612671565b61250b578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612510565b600090505b92915050565b6000808447101561255c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161255390613f77565b60405180910390fd5b6000835114156125a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259890613d37565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390613e97565b60405180910390fd5b809150509392505050565b606061266983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061289f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b6000818360000180549050116126f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126e790613d17565b60405180910390fd5b8260000182815481106126ff57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168460405160240161275393929190613b1e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b60008083600101600084815260200190815260200160002054905060008114612893576000600182039050600060018660000180549050039050600086600001828154811061280257fe5b906000526020600020015490508087600001848154811061281f57fe5b906000526020600020018190555060018301876001016000838152602001908152602001600020819055508660000180548061285757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612899565b60009150505b92915050565b60606128ae84846000856128b7565b90509392505050565b6060824710156128fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128f390613df7565b60405180910390fd5b61290585612493565b612944576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293b90613f37565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161296e9190613a28565b60006040518083038185875af1925050503d80600081146129ab576040519150601f19603f3d011682016040523d82523d6000602084013e6129b0565b606091505b50915091506129c08282866129cc565b92505050949350505050565b606083156129dc57829050612a2c565b6000835111156129ef5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a239190613cf5565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612aba81614313565b92915050565b60008083601f840112612ad257600080fd5b8235905067ffffffffffffffff811115612aeb57600080fd5b602083019150836020820283011115612b0357600080fd5b9250929050565b60008083601f840112612b1c57600080fd5b8235905067ffffffffffffffff811115612b3557600080fd5b602083019150836020820283011115612b4d57600080fd5b9250929050565b600081519050612b638161432a565b92915050565b600081359050612b7881614341565b92915050565b600081359050612b8d81614358565b92915050565b60008083601f840112612ba557600080fd5b8235905067ffffffffffffffff811115612bbe57600080fd5b602083019150836001820283011115612bd657600080fd5b9250929050565b600081359050612bec8161436f565b92915050565b60008083601f840112612c0457600080fd5b8235905067ffffffffffffffff811115612c1d57600080fd5b602083019150836001820283011115612c3557600080fd5b9250929050565b600060c08284031215612c4e57600080fd5b612c5860c0614029565b90506000612c6884828501612aab565b6000830152506020612c7c84828501612aab565b6020830152506040612c9084828501612aab565b6040830152506060612ca484828501612cd8565b6060830152506080612cb884828501612cd8565b60808301525060a0612ccc84828501612cd8565b60a08301525092915050565b600081359050612ce78161437f565b92915050565b600081519050612cfc8161437f565b92915050565b600060208284031215612d1457600080fd5b6000612d2284828501612aab565b91505092915050565b60008060008060008060008060006101208a8c031215612d4a57600080fd5b6000612d588c828d01612aab565b9950506020612d698c828d01612aab565b9850506040612d7a8c828d01612cd8565b9750506060612d8b8c828d01612cd8565b9650506080612d9c8c828d01612cd8565b95505060a0612dad8c828d01612cd8565b94505060c0612dbe8c828d01612cd8565b93505060e0612dcf8c828d01612cd8565b925050610100612de18c828d01612bdd565b9150509295985092959850929598565b60008060008060608587031215612e0757600080fd5b6000612e1587828801612aab565b9450506020612e2687828801612cd8565b935050604085013567ffffffffffffffff811115612e4357600080fd5b612e4f87828801612b93565b925092505092959194509250565b60008060008060408587031215612e7357600080fd5b600085013567ffffffffffffffff811115612e8d57600080fd5b612e9987828801612b0a565b9450945050602085013567ffffffffffffffff811115612eb857600080fd5b612ec487828801612ac0565b925092505092959194509250565b600060208284031215612ee457600080fd5b6000612ef284828501612b54565b91505092915050565b60008060408385031215612f0e57600080fd5b6000612f1c85828601612b69565b9250506020612f2d85828601612aab565b9150509250929050565b600080600060608486031215612f4c57600080fd5b6000612f5a86828701612b69565b9350506020612f6b86828701612aab565b9250506040612f7c86828701612aab565b9150509250925092565b600060208284031215612f9857600080fd5b6000612fa684828501612b7e565b91505092915050565b60008060208385031215612fc257600080fd5b600083013567ffffffffffffffff811115612fdc57600080fd5b612fe885828601612bf2565b92509250509250929050565b60008060006040848603121561300957600080fd5b600084013567ffffffffffffffff81111561302357600080fd5b61302f86828701612bf2565b9350935050602061304286828701612aab565b9150509250925092565b600060c0828403121561305e57600080fd5b600061306c84828501612c3c565b91505092915050565b60006020828403121561308757600080fd5b600061309584828501612cd8565b91505092915050565b6000602082840312156130b057600080fd5b60006130be84828501612ced565b91505092915050565b60006130d383836130df565b60208301905092915050565b6130e8816140d0565b82525050565b6130f7816140d0565b82525050565b61310e613109826140d0565b614289565b82525050565b600061311f8261406a565b6131298185614098565b93506131348361405a565b8060005b8381101561316557815161314c88826130c7565b97506131578361408b565b925050600181019050613138565b5085935050505092915050565b61317b816140e2565b82525050565b61319261318d8261411a565b6142a5565b82525050565b6131a96131a482614146565b6142af565b82525050565b6131c06131bb826140ee565b61429b565b82525050565b6131d76131d282614172565b6142b9565b82525050565b6131e68161419e565b82525050565b6131fd6131f88261419e565b6142c3565b82525050565b600061320f83856140a9565b935061321c838584614247565b82840190509392505050565b600061323382614075565b61323d81856140a9565b935061324d818560208601614256565b80840191505092915050565b61326281614211565b82525050565b61327181614235565b82525050565b600061328383856140b4565b9350613290838584614247565b613299836142e1565b840190509392505050565b60006132b083856140c5565b93506132bd838584614247565b82840190509392505050565b60006132d482614080565b6132de81856140b4565b93506132ee818560208601614256565b6132f7816142e1565b840191505092915050565b600061330f6022836140b4565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006133756020836140b4565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006133b56015836140b4565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b60006133f5600c836140b4565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613435601a836140b4565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006134756026836140b4565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134db6020836140b4565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061351b6026836140b4565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135816012836140b4565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b60006135c1601b836140b4565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b60006136016019836140b4565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000613641601d836140b4565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006136816019836140b4565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b60006136c16015836140b4565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b60006137016020836140b4565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006137416018836140b4565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006137816019836140b4565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b60006137c1601d836140b4565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613801602a836140b4565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613867601d836140b4565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b60006138a76019836140b4565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138f060008501826130df565b50602082015161390360208501826130df565b50604082015161391660408501826130df565b5060608201516139296060850182613955565b50608082015161393c6080850182613955565b5060a082015161394f60a0850182613955565b50505050565b61395e81614207565b82525050565b61396d81614207565b82525050565b600061397f8287613181565b600a8201915061398f8286613181565b600a8201915061399f82856131c6565b6014820191506139af8284613198565b600f8201915081905095945050505050565b60006139cd82876131af565b6001820191506139dd82866130fd565b6014820191506139ed82856131ec565b6020820191506139fd82846131ec565b60208201915081905095945050505050565b6000613a1c828486613203565b91508190509392505050565b6000613a348284613228565b915081905092915050565b6000613a4c8284866132a4565b91508190509392505050565b6000602082019050613a6d60008301846130ee565b92915050565b600061016082019050613a89600083018e6130ee565b613a96602083018d6130ee565b613aa3604083018c6130ee565b613ab0606083018b6130ee565b613abd608083018a613964565b613aca60a0830189613964565b613ad760c0830188613964565b613ae460e0830187613964565b613af2610100830186613964565b613b00610120830185613964565b613b0e610140830184613268565b9c9b505050505050505050505050565b600061010082019050613b3460008301866130ee565b613b4160208301856130ee565b613b4e60408301846138da565b949350505050565b6000606082019050613b6b60008301866130ee565b613b7860208301856130ee565b613b856040830184613964565b949350505050565b6000604082019050613ba260008301856130ee565b613baf6020830184613964565b9392505050565b600061010082019050613bcc600083018b6130ee565b613bd9602083018a613964565b613be66040830189613964565b613bf36060830188613964565b613c006080830187613964565b613c0d60a0830186613964565b613c1a60c0830185613964565b613c2760e0830184613268565b9998505050505050505050565b60006020820190508181036000830152613c4e8184613114565b905092915050565b6000602082019050613c6b6000830184613172565b92915050565b6000608082019050613c8660008301876131dd565b613c936020830186613964565b613ca06040830185613964565b613cad6060830184613964565b95945050505050565b6000602082019050613ccb6000830184613259565b92915050565b60006020820190508181036000830152613cec818486613277565b90509392505050565b60006020820190508181036000830152613d0f81846132c9565b905092915050565b60006020820190508181036000830152613d3081613302565b9050919050565b60006020820190508181036000830152613d5081613368565b9050919050565b60006020820190508181036000830152613d70816133a8565b9050919050565b60006020820190508181036000830152613d90816133e8565b9050919050565b60006020820190508181036000830152613db081613428565b9050919050565b60006020820190508181036000830152613dd081613468565b9050919050565b60006020820190508181036000830152613df0816134ce565b9050919050565b60006020820190508181036000830152613e108161350e565b9050919050565b60006020820190508181036000830152613e3081613574565b9050919050565b60006020820190508181036000830152613e50816135b4565b9050919050565b60006020820190508181036000830152613e70816135f4565b9050919050565b60006020820190508181036000830152613e9081613634565b9050919050565b60006020820190508181036000830152613eb081613674565b9050919050565b60006020820190508181036000830152613ed0816136b4565b9050919050565b60006020820190508181036000830152613ef0816136f4565b9050919050565b60006020820190508181036000830152613f1081613734565b9050919050565b60006020820190508181036000830152613f3081613774565b9050919050565b60006020820190508181036000830152613f50816137b4565b9050919050565b60006020820190508181036000830152613f70816137f4565b9050919050565b60006020820190508181036000830152613f908161385a565b9050919050565b60006020820190508181036000830152613fb08161389a565b9050919050565b6000602082019050613fcc6000830184613964565b92915050565b60008083356001602003843603038112613feb57600080fd5b80840192508235915067ffffffffffffffff82111561400957600080fd5b60208301925060018202360383131561402157600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff821117156140505761404f6142df565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006140db826141e7565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506141e2826142ff565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061421c82614223565b9050919050565b600061422e826141e7565b9050919050565b6000614240826141d4565b9050919050565b82818337600083830152505050565b60005b83811015614274578082015181840152602081019050614259565b83811115614283576000848401525b50505050565b6000614294826142cd565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006142d8826142f2565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b600381106143105761430f6142df565b5b50565b61431c816140d0565b811461432757600080fd5b50565b614333816140e2565b811461433e57600080fd5b50565b61434a8161419e565b811461435557600080fd5b50565b614361816141a8565b811461436c57600080fd5b50565b6003811061437c57600080fd5b50565b61438881614207565b811461439357600080fd5b5056fea26469706673582212202dadc0d09d62f32774ff0e2d49549f8768c210a71ba59d9013abe0c5a6bef31064736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061018e5760003560e01c80638da5cb5b116100de578063b6b55f2511610097578063cf497e6c11610071578063cf497e6c1461047f578063f1d24c451461049b578063f2fde38b146104cb578063fc0c546a146104e75761018e565b8063b6b55f2514610417578063bdb62fbe14610433578063c1ab13db146104635761018e565b80638da5cb5b146103675780638fa74a0e146103855780639c05fc60146103a3578063a3457466146103bf578063a4c0ed36146103dd578063a619486e146103f95761018e565b8063463013a21161014b57806368d30c2e1161012557806368d30c2e146102e15780636e03b8dc146102fd578063715018a61461032d57806379ee1bdf146103375761018e565b8063463013a21461028b578063586a5353146102a75780635975e00c146102c55761018e565b806303990a6c14610193578063045b7fe2146101af5780630602ba2b146101df5780630cd6178f1461020f5780632e1a7d4d1461023f57806343fb93d91461025b575b600080fd5b6101ad60048036038101906101a89190612faf565b610505565b005b6101c960048036038101906101c49190612d02565b6106ad565b6040516101d69190613a58565b60405180910390f35b6101f960048036038101906101f49190612f86565b6106e0565b6040516102069190613c56565b60405180910390f35b61022960048036038101906102249190612d02565b610721565b6040516102369190613a58565b60405180910390f35b61025960048036038101906102549190613075565b610754565b005b61027560048036038101906102709190612f37565b6108b1565b6040516102829190613a58565b60405180910390f35b6102a560048036038101906102a09190612ff4565b6108d6565b005b6102af610962565b6040516102bc9190613a58565b60405180910390f35b6102df60048036038101906102da9190612d02565b610986565b005b6102fb60048036038101906102f69190612d2b565b610b17565b005b61031760048036038101906103129190612f86565b610e5f565b6040516103249190613a58565b60405180910390f35b610335610e92565b005b610351600480360381019061034c9190612d02565b610fcc565b60405161035e9190613c56565b60405180910390f35b61036f610fe9565b60405161037c9190613a58565b60405180910390f35b61038d611012565b60405161039a9190613a58565b60405180910390f35b6103bd60048036038101906103b89190612e5d565b611036565b005b6103c7611163565b6040516103d49190613c34565b60405180910390f35b6103f760048036038101906103f29190612df1565b61123b565b005b6104016117a1565b60405161040e9190613a58565b60405180910390f35b610431600480360381019061042c9190613075565b6117c7565b005b61044d60048036038101906104489190612efb565b6118aa565b60405161045a9190613a58565b60405180910390f35b61047d60048036038101906104789190612d02565b6118bf565b005b61049960048036038101906104949190612d02565b6119e0565b005b6104b560048036038101906104b09190612f86565b611b53565b6040516104c29190613a58565b60405180910390f35b6104e560048036038101906104e09190612d02565b611bce565b005b6104ef611d77565b6040516104fc9190613cb6565b60405180910390f35b61050d611da1565b73ffffffffffffffffffffffffffffffffffffffff1661052b610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610581576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161057890613ed7565b60405180910390fd5b600061058d8383611da9565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c986866040516106a0929190613cd1565b60405180910390a4505050565b60076020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008073ffffffffffffffffffffffffffffffffffffffff1661070283611b53565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b60066020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61075c611da1565b73ffffffffffffffffffffffffffffffffffffffff1661077a610fe9565b73ffffffffffffffffffffffffffffffffffffffff16146107d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107c790613ed7565b60405180910390fd5b60008111610813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080a90613eb7565b60405180910390fd5b6108603382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516108a69190613fb7565b60405180910390a250565b60006108cd846108c085611ebd565b8051906020012084611f33565b90509392505050565b6108de611da1565b73ffffffffffffffffffffffffffffffffffffffff166108fc610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161094990613ed7565b60405180910390fd5b61095d838383611f77565b505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b61098e611da1565b73ffffffffffffffffffffffffffffffffffffffff166109ac610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610a02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f990613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6990613d97565b60405180910390fd5b610a8681600261215990919063ffffffff16565b610ac5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610abc90613f17565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610b0c9190613c56565b60405180910390a250565b610b1f611da1565b73ffffffffffffffffffffffffffffffffffffffff16610b3d610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610b93576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b8a90613ed7565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610bef9190613a58565b60206040518083038186803b158015610c0757600080fd5b505afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f919061309e565b1015610c80576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c7790613dd7565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610cd19b9a99989796959493929190613a73565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610d668280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612189565b9050610db5818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610e4a989796959493929190613bb6565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610e9a611da1565b73ffffffffffffffffffffffffffffffffffffffff16610eb8610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614610f0e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f0590613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610fe282600261220590919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b61103e611da1565b73ffffffffffffffffffffffffffffffffffffffff1661105c610fe9565b73ffffffffffffffffffffffffffffffffffffffff16146110b2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a990613ed7565b60405180910390fd5b8181905084849050146110fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f190613d57565b60405180910390fd5b60005b8484905081101561115c5761114f85858381811061111757fe5b90506020028101906111299190613fd2565b85858581811061113557fe5b905060200201602081019061114a9190612d02565b611f77565b80806001019150506110fd565b5050505050565b6060806111706002612235565b67ffffffffffffffff8111801561118657600080fd5b506040519080825280602002602001820160405280156111b55781602001602082028036833780820191505090505b50905060005b6111c56002612235565b811015611233576111e081600261224a90919063ffffffff16565b8282815181106111ec57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff168152505080806001019150506111bb565b508091505090565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146112c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112c090613d77565b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1614611357576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161134e90613e17565b60405180910390fd5b61135f612a33565b828281019061136e919061304c565b9050600073ffffffffffffffffffffffffffffffffffffffff1660066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146114bc576114b760066000836000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b6116ce565b6000806114e085856040516114d2929190613a0f565b604051809103902084612264565b915091508060066000856000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260000151600760008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506116358187600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611e379092919063ffffffff16565b826000015173ffffffffffffffffffffffffffffffffffffffff16836040015173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167fd74fe60cbf1e5bf07ef3fad0e00c45f66345c5226474786d8dc086527dc8414785876060015188608001518960a001516040516116c39493929190613c71565b60405180910390a450505b60066000826000015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16816000015173ffffffffffffffffffffffffffffffffffffffff167fe34903cfa4ad8362651171309d05bcbc2fc581a5ec83ca7b0c8d10743de766e2866040516117929190613fb7565b60405180910390a35050505050565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161180a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180190613eb7565b60405180910390fd5b611859333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166122bb909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e8260405161189f9190613fb7565b60405180910390a250565b60006118b78383306108b1565b905092915050565b6118c7611da1565b73ffffffffffffffffffffffffffffffffffffffff166118e5610fe9565b73ffffffffffffffffffffffffffffffffffffffff161461193b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193290613ed7565b60405180910390fd5b61194f81600261234490919063ffffffff16565b61198e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161198590613e37565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516119d59190613c56565b60405180910390a250565b6119e8611da1565b73ffffffffffffffffffffffffffffffffffffffff16611a06610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614611a5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a5390613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611acc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac390613e57565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b611bd6611da1565b73ffffffffffffffffffffffffffffffffffffffff16611bf4610fe9565b73ffffffffffffffffffffffffffffffffffffffff1614611c4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c4190613ed7565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611cba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cb190613db7565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b6000611e2f83836040516024016040516020818303038152906040529190604051611dd5929190613a3f565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612374565b905092915050565b611eb88363a9059cbb60e01b8484604051602401611e56929190613b8d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506123cc565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611f199493929190613973565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611f5194939291906139c1565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611fe6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fdd90613e77565b60405180910390fd5b611fef81612493565b61202e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202590613f97565b60405180910390fd5b600061203a8484611da9565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9878760405161214b929190613cd1565b60405180910390a450505050565b6000612181836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6124a6565b905092915050565b6000806121a060008661219b87611ebd565b612516565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156121fa576121f88184612627565b505b809150509392505050565b600061222d836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612671565b905092915050565b600061224382600001612694565b9050919050565b600061225983600001836126a5565b60001c905092915050565b600080606061227284612712565b905060006122a386600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684612189565b90508180519060200120819350935050509250929050565b61233e846323b872dd60e01b8585856040516024016122dc93929190613b56565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506123cc565b50505050565b600061236c836000018373ffffffffffffffffffffffffffffffffffffffff1660001b6127b7565b905092915050565b600060048251146123ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123b190613ef7565b60405180910390fd5b60006020830151905080915050919050565b606061242e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661289f9092919063ffffffff16565b905060008151111561248e578080602001905181019061244e9190612ed2565b61248d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161248490613f57565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b60006124b28383612671565b61250b578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050612510565b600090505b92915050565b6000808447101561255c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161255390613f77565b60405180910390fd5b6000835114156125a1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259890613d37565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561261c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161261390613e97565b60405180910390fd5b809150509392505050565b606061266983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c6564000081525061289f565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b6000818360000180549050116126f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126e790613d17565b60405180910390fd5b8260000182815481106126ff57fe5b9060005260206000200154905092915050565b60606320dc203d60e01b30600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168460405160240161275393929190613b1e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050919050565b60008083600101600084815260200190815260200160002054905060008114612893576000600182039050600060018660000180549050039050600086600001828154811061280257fe5b906000526020600020015490508087600001848154811061281f57fe5b906000526020600020018190555060018301876001016000838152602001908152602001600020819055508660000180548061285757fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612899565b60009150505b92915050565b60606128ae84846000856128b7565b90509392505050565b6060824710156128fc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128f390613df7565b60405180910390fd5b61290585612493565b612944576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161293b90613f37565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161296e9190613a28565b60006040518083038185875af1925050503d80600081146129ab576040519150601f19603f3d011682016040523d82523d6000602084013e6129b0565b606091505b50915091506129c08282866129cc565b92505050949350505050565b606083156129dc57829050612a2c565b6000835111156129ef5782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a239190613cf5565b60405180910390fd5b9392505050565b6040518060c00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff1681526020016000815260200160008152602001600081525090565b600081359050612aba81614313565b92915050565b60008083601f840112612ad257600080fd5b8235905067ffffffffffffffff811115612aeb57600080fd5b602083019150836020820283011115612b0357600080fd5b9250929050565b60008083601f840112612b1c57600080fd5b8235905067ffffffffffffffff811115612b3557600080fd5b602083019150836020820283011115612b4d57600080fd5b9250929050565b600081519050612b638161432a565b92915050565b600081359050612b7881614341565b92915050565b600081359050612b8d81614358565b92915050565b60008083601f840112612ba557600080fd5b8235905067ffffffffffffffff811115612bbe57600080fd5b602083019150836001820283011115612bd657600080fd5b9250929050565b600081359050612bec8161436f565b92915050565b60008083601f840112612c0457600080fd5b8235905067ffffffffffffffff811115612c1d57600080fd5b602083019150836001820283011115612c3557600080fd5b9250929050565b600060c08284031215612c4e57600080fd5b612c5860c0614029565b90506000612c6884828501612aab565b6000830152506020612c7c84828501612aab565b6020830152506040612c9084828501612aab565b6040830152506060612ca484828501612cd8565b6060830152506080612cb884828501612cd8565b60808301525060a0612ccc84828501612cd8565b60a08301525092915050565b600081359050612ce78161437f565b92915050565b600081519050612cfc8161437f565b92915050565b600060208284031215612d1457600080fd5b6000612d2284828501612aab565b91505092915050565b60008060008060008060008060006101208a8c031215612d4a57600080fd5b6000612d588c828d01612aab565b9950506020612d698c828d01612aab565b9850506040612d7a8c828d01612cd8565b9750506060612d8b8c828d01612cd8565b9650506080612d9c8c828d01612cd8565b95505060a0612dad8c828d01612cd8565b94505060c0612dbe8c828d01612cd8565b93505060e0612dcf8c828d01612cd8565b925050610100612de18c828d01612bdd565b9150509295985092959850929598565b60008060008060608587031215612e0757600080fd5b6000612e1587828801612aab565b9450506020612e2687828801612cd8565b935050604085013567ffffffffffffffff811115612e4357600080fd5b612e4f87828801612b93565b925092505092959194509250565b60008060008060408587031215612e7357600080fd5b600085013567ffffffffffffffff811115612e8d57600080fd5b612e9987828801612b0a565b9450945050602085013567ffffffffffffffff811115612eb857600080fd5b612ec487828801612ac0565b925092505092959194509250565b600060208284031215612ee457600080fd5b6000612ef284828501612b54565b91505092915050565b60008060408385031215612f0e57600080fd5b6000612f1c85828601612b69565b9250506020612f2d85828601612aab565b9150509250929050565b600080600060608486031215612f4c57600080fd5b6000612f5a86828701612b69565b9350506020612f6b86828701612aab565b9250506040612f7c86828701612aab565b9150509250925092565b600060208284031215612f9857600080fd5b6000612fa684828501612b7e565b91505092915050565b60008060208385031215612fc257600080fd5b600083013567ffffffffffffffff811115612fdc57600080fd5b612fe885828601612bf2565b92509250509250929050565b60008060006040848603121561300957600080fd5b600084013567ffffffffffffffff81111561302357600080fd5b61302f86828701612bf2565b9350935050602061304286828701612aab565b9150509250925092565b600060c0828403121561305e57600080fd5b600061306c84828501612c3c565b91505092915050565b60006020828403121561308757600080fd5b600061309584828501612cd8565b91505092915050565b6000602082840312156130b057600080fd5b60006130be84828501612ced565b91505092915050565b60006130d383836130df565b60208301905092915050565b6130e8816140d0565b82525050565b6130f7816140d0565b82525050565b61310e613109826140d0565b614289565b82525050565b600061311f8261406a565b6131298185614098565b93506131348361405a565b8060005b8381101561316557815161314c88826130c7565b97506131578361408b565b925050600181019050613138565b5085935050505092915050565b61317b816140e2565b82525050565b61319261318d8261411a565b6142a5565b82525050565b6131a96131a482614146565b6142af565b82525050565b6131c06131bb826140ee565b61429b565b82525050565b6131d76131d282614172565b6142b9565b82525050565b6131e68161419e565b82525050565b6131fd6131f88261419e565b6142c3565b82525050565b600061320f83856140a9565b935061321c838584614247565b82840190509392505050565b600061323382614075565b61323d81856140a9565b935061324d818560208601614256565b80840191505092915050565b61326281614211565b82525050565b61327181614235565b82525050565b600061328383856140b4565b9350613290838584614247565b613299836142e1565b840190509392505050565b60006132b083856140c5565b93506132bd838584614247565b82840190509392505050565b60006132d482614080565b6132de81856140b4565b93506132ee818560208601614256565b6132f7816142e1565b840191505092915050565b600061330f6022836140b4565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006133756020836140b4565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006133b56015836140b4565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b60006133f5600c836140b4565b91507f4f4e4c595f4741544557415900000000000000000000000000000000000000006000830152602082019050919050565b6000613435601a836140b4565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006134756026836140b4565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006134db6020836140b4565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b600061351b6026836140b4565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135816012836140b4565b91507f4f4e4c595f5452414e534645525f544f4f4c00000000000000000000000000006000830152602082019050919050565b60006135c1601b836140b4565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b60006136016019836140b4565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000613641601d836140b4565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b60006136816019836140b4565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b60006136c16015836140b4565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b60006137016020836140b4565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006137416018836140b4565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b60006137816019836140b4565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b60006137c1601d836140b4565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613801602a836140b4565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613867601d836140b4565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b60006138a76019836140b4565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b60c0820160008201516138f060008501826130df565b50602082015161390360208501826130df565b50604082015161391660408501826130df565b5060608201516139296060850182613955565b50608082015161393c6080850182613955565b5060a082015161394f60a0850182613955565b50505050565b61395e81614207565b82525050565b61396d81614207565b82525050565b600061397f8287613181565b600a8201915061398f8286613181565b600a8201915061399f82856131c6565b6014820191506139af8284613198565b600f8201915081905095945050505050565b60006139cd82876131af565b6001820191506139dd82866130fd565b6014820191506139ed82856131ec565b6020820191506139fd82846131ec565b60208201915081905095945050505050565b6000613a1c828486613203565b91508190509392505050565b6000613a348284613228565b915081905092915050565b6000613a4c8284866132a4565b91508190509392505050565b6000602082019050613a6d60008301846130ee565b92915050565b600061016082019050613a89600083018e6130ee565b613a96602083018d6130ee565b613aa3604083018c6130ee565b613ab0606083018b6130ee565b613abd608083018a613964565b613aca60a0830189613964565b613ad760c0830188613964565b613ae460e0830187613964565b613af2610100830186613964565b613b00610120830185613964565b613b0e610140830184613268565b9c9b505050505050505050505050565b600061010082019050613b3460008301866130ee565b613b4160208301856130ee565b613b4e60408301846138da565b949350505050565b6000606082019050613b6b60008301866130ee565b613b7860208301856130ee565b613b856040830184613964565b949350505050565b6000604082019050613ba260008301856130ee565b613baf6020830184613964565b9392505050565b600061010082019050613bcc600083018b6130ee565b613bd9602083018a613964565b613be66040830189613964565b613bf36060830188613964565b613c006080830187613964565b613c0d60a0830186613964565b613c1a60c0830185613964565b613c2760e0830184613268565b9998505050505050505050565b60006020820190508181036000830152613c4e8184613114565b905092915050565b6000602082019050613c6b6000830184613172565b92915050565b6000608082019050613c8660008301876131dd565b613c936020830186613964565b613ca06040830185613964565b613cad6060830184613964565b95945050505050565b6000602082019050613ccb6000830184613259565b92915050565b60006020820190508181036000830152613cec818486613277565b90509392505050565b60006020820190508181036000830152613d0f81846132c9565b905092915050565b60006020820190508181036000830152613d3081613302565b9050919050565b60006020820190508181036000830152613d5081613368565b9050919050565b60006020820190508181036000830152613d70816133a8565b9050919050565b60006020820190508181036000830152613d90816133e8565b9050919050565b60006020820190508181036000830152613db081613428565b9050919050565b60006020820190508181036000830152613dd081613468565b9050919050565b60006020820190508181036000830152613df0816134ce565b9050919050565b60006020820190508181036000830152613e108161350e565b9050919050565b60006020820190508181036000830152613e3081613574565b9050919050565b60006020820190508181036000830152613e50816135b4565b9050919050565b60006020820190508181036000830152613e70816135f4565b9050919050565b60006020820190508181036000830152613e9081613634565b9050919050565b60006020820190508181036000830152613eb081613674565b9050919050565b60006020820190508181036000830152613ed0816136b4565b9050919050565b60006020820190508181036000830152613ef0816136f4565b9050919050565b60006020820190508181036000830152613f1081613734565b9050919050565b60006020820190508181036000830152613f3081613774565b9050919050565b60006020820190508181036000830152613f50816137b4565b9050919050565b60006020820190508181036000830152613f70816137f4565b9050919050565b60006020820190508181036000830152613f908161385a565b9050919050565b60006020820190508181036000830152613fb08161389a565b9050919050565b6000602082019050613fcc6000830184613964565b92915050565b60008083356001602003843603038112613feb57600080fd5b80840192508235915067ffffffffffffffff82111561400957600080fd5b60208301925060018202360383131561402157600080fd5b509250929050565b6000604051905081810181811067ffffffffffffffff821117156140505761404f6142df565b5b8060405250919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006140db826141e7565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506141e2826142ff565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061421c82614223565b9050919050565b600061422e826141e7565b9050919050565b6000614240826141d4565b9050919050565b82818337600083830152505050565b60005b83811015614274578082015181840152602081019050614259565b83811115614283576000848401525b50505050565b6000614294826142cd565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006142d8826142f2565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b600381106143105761430f6142df565b5b50565b61431c816140d0565b811461432757600080fd5b50565b614333816140e2565b811461433e57600080fd5b50565b61434a8161419e565b811461435557600080fd5b50565b614361816141a8565b811461436c57600080fd5b50565b6003811061437c57600080fd5b50565b61438881614207565b811461439357600080fd5b5056fea26469706673582212202dadc0d09d62f32774ff0e2d49549f8768c210a71ba59d9013abe0c5a6bef31064736f6c63430007030033", + "devdoc": { + "events": { + "LockedTokensReceivedFromL1(address,address,uint256)": { + "details": "Emitted when locked tokens are received from L1 (whether the wallet had already been received or not)" + }, + "TokenLockCreatedFromL1(address,bytes32,address,uint256,uint256,uint256,address)": { + "details": "Event emitted when a wallet is received and created from L1" + } + }, + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Address of the L2 GRT token contract", + "_l1TransferTool": "Address of the L1 transfer tool contract (in L1, without aliasing)", + "_l2Gateway": "Address of the L2GraphTokenGateway contract", + "_masterCopy": "Address of the master copy of the L2GraphTokenLockWallet implementation" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address)": { + "details": "Uses address(this) as deployer to compute the address. Only for backwards compatibility.", + "params": { + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "onTokenTransfer(address,uint256,bytes)": { + "details": "This function will create a new wallet if it doesn't exist yet, or send the tokens to the existing wallet if it does.", + "params": { + "_amount": "Amount of tokens received", + "_data": "Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct", + "_from": "Address of the sender in L1, which must be the L1GraphTokenLockTransferTool" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor for the L2GraphTokenLockManager contract." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "l1TransferTool()": { + "notice": "Address of the L1 transfer tool contract (in L1, no aliasing)" + }, + "l1WalletToL2Wallet(address)": { + "notice": "Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received) L1 address => L2 address" + }, + "l2Gateway()": { + "notice": "Address of the L2GraphTokenGateway" + }, + "l2WalletToL1Wallet(address)": { + "notice": "Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received) L2 address => L1 address" + }, + "onTokenTransfer(address,uint256,bytes)": { + "notice": "This function is called by the L2GraphTokenGateway when tokens are sent from L1." + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. In particular, this L2 variant is designed to receive token lock wallets from L1, through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 6154, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l1WalletToL2Wallet", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 6159, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "l2WalletToL1Wallet", + "offset": 0, + "slot": "7", + "type": "t_mapping(t_address,t_address)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/L2GraphTokenLockManager.sol:L2GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockTransferTool.json b/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockTransferTool.json new file mode 100644 index 000000000..b8c71758e --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockTransferTool.json @@ -0,0 +1,110 @@ +{ + "address": "0xe21cd62E1E0CD68476C47F518980226C0a05fB19", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "contract ITokenGateway", + "name": "_l2Gateway", + "type": "address" + }, + { + "internalType": "address", + "name": "_l1GraphToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedFundsSentToL1", + "type": "event" + }, + { + "inputs": [], + "name": "graphToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l1GraphToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Gateway", + "outputs": [ + { + "internalType": "contract ITokenGateway", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawToL1Locked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x4785cb6bfeae00d727ed1199ad2724772507d6631135c73797069382a58af7d3" +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockWallet.json b/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockWallet.json new file mode 100644 index 000000000..b63a7619d --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockWallet.json @@ -0,0 +1,1156 @@ +{ + "address": "0x45FfA6DaD9F49C5018E5345eAdf6E2e5C7116F64", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "l1Address", + "type": "address" + }, + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + } + ], + "internalType": "struct L2GraphTokenLockManager.TransferredWalletData", + "name": "_walletData", + "type": "tuple" + } + ], + "name": "initializeFromL1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xc397d5636ef92c873da6587fc0124b89c87f7b12a8fa9c953868da0d501a5d05", + "receipt": { + "to": null, + "from": "0xadE6B8EB69a49B56929C1d4F4b428d791861dB6f", + "contractAddress": "0x45FfA6DaD9F49C5018E5345eAdf6E2e5C7116F64", + "transactionIndex": 1, + "gasUsed": "4063753", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x85b790be25ea48fba17a32160b852c89d43e36971a6a1732139f0c78483f96ea", + "transactionHash": "0xc397d5636ef92c873da6587fc0124b89c87f7b12a8fa9c953868da0d501a5d05", + "logs": [], + "blockNumber": 674827, + "cumulativeGasUsed": "4063753", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "095bd30babc75057be19228ca1fd7aa4", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"l1Address\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"}],\"internalType\":\"struct L2GraphTokenLockManager.TransferredWalletData\",\"name\":\"_walletData\",\"type\":\"tuple\"}],\"name\":\"initializeFromL1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"L2GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. This L2 variant includes a special initializer so that it can be created from a wallet's data received from L1. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1, so releasing surplus tokens might also only be possible by bridging tokens back to L1. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/L2GraphTokenLockWallet.sol\":\"L2GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/ICallhookReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-2.0-or-later\\n\\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\\n\\n/**\\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\\n * be allowlisted by the governor, but also implement this interface that contains\\n * the function that will actually be called by the L2GraphTokenGateway.\\n */\\npragma solidity ^0.7.3;\\n\\ninterface ICallhookReceiver {\\n /**\\n * @notice Receive tokens with a callhook from the bridge\\n * @param _from Token sender in L1\\n * @param _amount Amount of tokens that were transferred\\n * @param _data ABI-encoded callhook data\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\\n}\\n\",\"keccak256\":\"0xb90eae14e8bac012a4b99fabe7a1110f70143eb78476ea0d6b52557ef979fa0e\",\"license\":\"GPL-2.0-or-later\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { ICallhookReceiver } from \\\"./ICallhookReceiver.sol\\\";\\nimport { GraphTokenLockManager } from \\\"./GraphTokenLockManager.sol\\\";\\nimport { L2GraphTokenLockWallet } from \\\"./L2GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\\n * the L2GraphTokenLockTransferTool contract.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\\n using SafeERC20 for IERC20;\\n\\n /// @dev Struct to hold the data of a transferred wallet; this is\\n /// the data that must be encoded in L1 to send a wallet to L2.\\n struct TransferredWalletData {\\n address l1Address;\\n address owner;\\n address beneficiary;\\n uint256 managedAmount;\\n uint256 startTime;\\n uint256 endTime;\\n }\\n\\n /// Address of the L2GraphTokenGateway\\n address public immutable l2Gateway;\\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\\n address public immutable l1TransferTool;\\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\\n /// L1 address => L2 address\\n mapping(address => address) public l1WalletToL2Wallet;\\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\\n /// L2 address => L1 address\\n mapping(address => address) public l2WalletToL1Wallet;\\n\\n /// @dev Event emitted when a wallet is received and created from L1\\n event TokenLockCreatedFromL1(\\n address indexed contractAddress,\\n bytes32 initHash,\\n address indexed beneficiary,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n address indexed l1Address\\n );\\n\\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\\n /// had already been received or not)\\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\\n\\n /**\\n * @dev Checks that the sender is the L2GraphTokenGateway.\\n */\\n modifier onlyL2Gateway() {\\n require(msg.sender == l2Gateway, \\\"ONLY_GATEWAY\\\");\\n _;\\n }\\n\\n /**\\n * @notice Constructor for the L2GraphTokenLockManager contract.\\n * @param _graphToken Address of the L2 GRT token contract\\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\\n */\\n constructor(\\n IERC20 _graphToken,\\n address _masterCopy,\\n address _l2Gateway,\\n address _l1TransferTool\\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\\n l2Gateway = _l2Gateway;\\n l1TransferTool = _l1TransferTool;\\n }\\n\\n /**\\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\\n * the existing wallet if it does.\\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\\n * @param _amount Amount of tokens received\\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\\n */\\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\\n require(_from == l1TransferTool, \\\"ONLY_TRANSFER_TOOL\\\");\\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\\n\\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\\n // If the wallet was already received, just send the tokens to the L2 address\\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\\n } else {\\n // Create contract using a minimal proxy and call initializer\\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _amount);\\n\\n emit TokenLockCreatedFromL1(\\n contractAddress,\\n initHash,\\n walletData.beneficiary,\\n walletData.managedAmount,\\n walletData.startTime,\\n walletData.endTime,\\n walletData.l1Address\\n );\\n }\\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\\n }\\n\\n /**\\n * @dev Deploy a token lock wallet with data received from L1\\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\\n * @param _walletData Data of the wallet to be created\\n * @return Hash of the initialization calldata\\n * @return Address of the created contract\\n */\\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\\n bytes memory initializer = _encodeInitializer(_walletData);\\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\\n return (keccak256(initializer), contractAddress);\\n }\\n\\n /**\\n * @dev Encode the initializer for the token lock wallet received from L1\\n * @param _walletData Data of the wallet to be created\\n * @return Encoded initializer calldata, including the function signature\\n */\\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\\n return\\n abi.encodeWithSelector(\\n L2GraphTokenLockWallet.initializeFromL1.selector,\\n address(this),\\n address(_token),\\n _walletData\\n );\\n }\\n}\\n\",\"keccak256\":\"0x34ca0ffc898ce3615a000d53a9c58708354b8cd8093b3c61decfe7388f0c16e0\",\"license\":\"MIT\"},\"contracts/L2GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport { L2GraphTokenLockManager } from \\\"./L2GraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title L2GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * This L2 variant includes a special initializer so that it can be created from\\n * a wallet's data received from L1. These transferred wallets will not allow releasing\\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\\n *\\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\\n // Initializer when created from a message from L1\\n function initializeFromL1(\\n address _manager,\\n address _token,\\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\\n ) external {\\n require(!isInitialized, \\\"Already initialized\\\");\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_walletData.owner);\\n beneficiary = _walletData.beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _walletData.managedAmount;\\n\\n startTime = _walletData.startTime;\\n endTime = _walletData.endTime;\\n periods = 1;\\n isAccepted = true;\\n\\n // Optionals\\n releaseStartTime = _walletData.endTime;\\n revocable = Revocability.Disabled;\\n\\n _setManager(_manager);\\n }\\n}\\n\",\"keccak256\":\"0x8842140c2c7924be4ab1bca71e0b0ad6dd1dba6433cfdc523bfd204288b25d20\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @dev Uses address(this) as deployer to compute the address. Only for backwards compatibility.\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation\\n ) public view returns (address) {\\n return getDeploymentAddress(_salt, _implementation, address(this));\\n }\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0xc0ad119f676fe82b234fd5c830d9bc443e9038c0cfe5dc4de3a3bf621d3f69df\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506148f5806100206000396000f3fe6080604052600436106102605760003560e01c80637bdf05af11610144578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610bc7578063e8dda6f514610bf0578063e97d87d514610c1b578063ebbab99214610c46578063f2fde38b14610c71578063fc0c546a14610c9a576102a0565b8063bc0163c114610af4578063bd896dcb14610b1f578063ce845d1d14610b48578063d0ebdbe714610b73578063d18e81b314610b9c576102a0565b80638da5cb5b116101085780638da5cb5b14610a0857806391f7cfb914610a33578063a4caeb4214610a5e578063b0d1818c14610a89578063b470aade14610ab2578063b6549f7514610add576102a0565b80637bdf05af1461095957806386d00e021461098457806386d1a69f146109af578063872a7810146109c65780638a5bdf5c146109f1576102a0565b806338af3eed116101dd578063481c6a75116101a1578063481c6a751461087f5780635051a5ec146108aa5780635b940081146108d557806360e7994414610900578063715018a61461091757806378e979251461092e576102a0565b806338af3eed146107a8578063392e53cd146107d3578063398057a3146107fe57806344b1231f1461082957806345d30a1714610854576102a0565b806320dc203d1161022457806320dc203d146106e75780632a627814146107105780632bc9ed02146107275780633197cbb61461075257806337aeb0861461077d576102a0565b8063029c6c9f14610624578063060406181461064f5780630b80f7771461067a5780630dff24d5146106915780630fb5a6b4146106bc576102a0565b366102a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610297906141f3565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610327906143d3565b60405180910390fd5b60003414610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036a90614213565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103f49190614165565b60206040518083038186803b15801561040c57600080fd5b505afa158015610420573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610444919061338f565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ad906144d3565b60405180910390fd5b60006104c0610cc5565b9050610511826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d77565b506001600281111561051f57fe5b603b60009054906101000a900460ff16600281111561053a57fe5b141561062057600061054a610cc5565b90508181101561058c5760006105698284610dc190919063ffffffff16565b905061058081603f54610e1190919063ffffffff16565b603f81905550506105d2565b60006105a18383610dc190919063ffffffff16565b9050603f548110156105c7576105c281603f54610dc190919063ffffffff16565b6105ca565b60005b603f81905550505b6105da610e66565b603f54111561061e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061590614433565b60405180910390fd5b505b5050005b34801561063057600080fd5b50610639610ed5565b6040516106469190614673565b60405180910390f35b34801561065b57600080fd5b50610664610ef3565b6040516106719190614673565b60405180910390f35b34801561068657600080fd5b5061068f610f2e565b005b34801561069d57600080fd5b506106a661109b565b6040516106b39190614673565b60405180910390f35b3480156106c857600080fd5b506106d16110e2565b6040516106de9190614673565b60405180910390f35b3480156106f357600080fd5b5061070e600480360381019061070991906134a8565b611100565b005b34801561071c57600080fd5b5061072561129b565b005b34801561073357600080fd5b5061073c611500565b604051610749919061414a565b60405180910390f35b34801561075e57600080fd5b50610767611513565b6040516107749190614673565b60405180910390f35b34801561078957600080fd5b50610792611519565b60405161079f9190614673565b60405180910390f35b3480156107b457600080fd5b506107bd61151f565b6040516107ca91906140dd565b60405180910390f35b3480156107df57600080fd5b506107e8611545565b6040516107f5919061414a565b60405180910390f35b34801561080a57600080fd5b50610813611558565b6040516108209190614673565b60405180910390f35b34801561083557600080fd5b5061083e610e66565b60405161084b9190614673565b60405180910390f35b34801561086057600080fd5b5061086961155e565b6040516108769190614673565b60405180910390f35b34801561088b57600080fd5b50610894611564565b6040516108a1919061419b565b60405180910390f35b3480156108b657600080fd5b506108bf61158a565b6040516108cc919061414a565b60405180910390f35b3480156108e157600080fd5b506108ea61159d565b6040516108f79190614673565b60405180910390f35b34801561090c57600080fd5b506109156116a8565b005b34801561092357600080fd5b5061092c6118ee565b005b34801561093a57600080fd5b50610943611a3a565b6040516109509190614673565b60405180910390f35b34801561096557600080fd5b5061096e611a40565b60405161097b9190614673565b60405180910390f35b34801561099057600080fd5b50610999611a7c565b6040516109a69190614673565b60405180910390f35b3480156109bb57600080fd5b506109c4611a82565b005b3480156109d257600080fd5b506109db611c5e565b6040516109e891906141b6565b60405180910390f35b3480156109fd57600080fd5b50610a06611c71565b005b348015610a1457600080fd5b50610a1d611d4a565b604051610a2a91906140dd565b60405180910390f35b348015610a3f57600080fd5b50610a48611d73565b604051610a559190614673565b60405180910390f35b348015610a6a57600080fd5b50610a73611dd1565b604051610a809190614673565b60405180910390f35b348015610a9557600080fd5b50610ab06004803603810190610aab9190613562565b611dd7565b005b348015610abe57600080fd5b50610ac7611fd6565b604051610ad49190614673565b60405180910390f35b348015610ae957600080fd5b50610af2611ff9565b005b348015610b0057600080fd5b50610b09612291565b604051610b169190614673565b60405180910390f35b348015610b2b57600080fd5b50610b466004803603810190610b4191906133b8565b6122c3565b005b348015610b5457600080fd5b50610b5d610cc5565b604051610b6a9190614673565b60405180910390f35b348015610b7f57600080fd5b50610b9a6004803603810190610b959190613366565b6122eb565b005b348015610ba857600080fd5b50610bb1612385565b604051610bbe9190614673565b60405180910390f35b348015610bd357600080fd5b50610bee6004803603810190610be99190613366565b61238d565b005b348015610bfc57600080fd5b50610c05612508565b604051610c129190614673565b60405180910390f35b348015610c2757600080fd5b50610c3061250e565b604051610c3d9190614673565b60405180910390f35b348015610c5257600080fd5b50610c5b612514565b604051610c689190614673565b60405180910390f35b348015610c7d57600080fd5b50610c986004803603810190610c939190613366565b612536565b005b348015610ca657600080fd5b50610caf6126f1565b604051610cbc9190614180565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d2291906140dd565b60206040518083038186803b158015610d3a57600080fd5b505afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d72919061358b565b905090565b6060610db983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612717565b905092915050565b600082821115610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90614333565b60405180910390fd5b818303905092915050565b600080828401905083811015610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e53906142b3565b60405180910390fd5b8091505092915050565b6000600280811115610e7457fe5b603b60009054906101000a900460ff166002811115610e8f57fe5b1415610e9f576035549050610ed2565b6000603a54118015610eb95750603a54610eb7612385565b105b15610ec75760009050610ed2565b610ecf611d73565b90505b90565b6000610eee60385460355461272f90919063ffffffff16565b905090565b6000610f296001610f1b610f05611fd6565b610f0d611a40565b61272f90919063ffffffff16565b610e1190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb390614493565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514611012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100990614313565b60405180910390fd5b61106d61101d611d4a565b611025610cc5565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b6000806110a6610cc5565b905060006110b2612291565b9050808211156110d8576110cf8183610dc190919063ffffffff16565b925050506110df565b6000925050505b90565b60006110fb603654603754610dc190919063ffffffff16565b905090565b603b60029054906101000a900460ff1615611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114790614533565b60405180910390fd5b6001603b60026101000a81548160ff0219169083151502179055506111868160200160208101906111819190613366565b61280b565b8060400160208101906111999190613366565b603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806060013560358190555080608001356036819055508060a0013560378190555060016038819055506001603b60036101000a81548160ff0219169083151502179055508060a001356039819055506002603b60006101000a81548160ff0219169083600281111561128857fe5b0217905550611296836128a9565b505050565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132290614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561139557600080fd5b505afa1580156113a9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113d291906134f8565b905060005b81518110156114d057603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061142a57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b8152600401611470929190614121565b602060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c29190613539565b5080806001019150506113d7565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156115ab57fe5b603b60009054906101000a900460ff1660028111156115c657fe5b14156115db576115d4612a27565b90506116a5565b60006039541180156115f557506039546115f3612385565b105b1561160357600090506116a5565b6001600281111561161057fe5b603b60009054906101000a900460ff16600281111561162b57fe5b14801561163a57506000603a54115b801561164e5750603a5461164c612385565b105b1561165c57600090506116a5565b600061168e603f54611680603c54611672611d73565b610dc190919063ffffffff16565b610dc190919063ffffffff16565b90506116a161169b610cc5565b82612ae1565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172f90614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906117df91906134f8565b905060005b81518110156118be57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061183757fe5b602002602001015160006040518363ffffffff1660e01b815260040161185e9291906140f8565b602060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b09190613539565b5080806001019150506117e4565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197390614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b600080611a4b612385565b90506036548111611a60576000915050611a79565b611a7560365482610dc190919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0990614593565b60405180910390fd5b6000611b1c61159d565b905060008111611b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b58906145f3565b60405180910390fd5b611b7681603c54610e1190919063ffffffff16565b603c81905550611beb603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611c539190614673565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890614593565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611d7e612385565b9050603654811015611d94576000915050611dce565b603754811115611da957603554915050611dce565b611dca611db4610ed5565b611dbc612514565b612afa90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5e90614593565b60405180910390fd5b60008111611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea190614413565b60405180910390fd5b80611eb361109b565b1015611ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eeb90614513565b60405180910390fd5b611f63603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611fcb9190614673565b60405180910390a250565b6000611ff4603854611fe66110e2565b61272f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614493565b60405180910390fd5b6001600281111561209457fe5b603b60009054906101000a900460ff1660028111156120af57fe5b146120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614553565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213c90614653565b60405180910390fd5b6000612163612152610e66565b603554610dc190919063ffffffff16565b9050600081116121a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219f906142d3565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061221e6121d5611d4a565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516122869190614673565b60405180910390a250565b60006122be603d546122b0603c54603554610dc190919063ffffffff16565b610dc190919063ffffffff16565b905090565b6122d58a8a8a8a8a8a8a8a8a8a612b6a565b6122de8b6128a9565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237090614493565b60405180910390fd5b612382816128a9565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461241d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161241490614593565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561248d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612484906143b3565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d816040516124fd91906140dd565b60405180910390a150565b603f5481565b60395481565b60006125316001612523610ef3565b610dc190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bb90614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262b90614293565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606127268484600085612ff4565b90509392505050565b6000808211612773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276a90614393565b60405180910390fd5b81838161277c57fe5b04905092915050565b6128068363a9059cbb60e01b84846040516024016127a4929190614121565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613109565b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291090614573565b60405180910390fd5b612922816131d0565b612961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612958906143f3565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b600080603954118015612a425750603954612a40612385565b105b15612a505760009050612ade565b60016002811115612a5d57fe5b603b60009054906101000a900460ff166002811115612a7857fe5b148015612a8757506000603a54115b8015612a9b5750603a54612a99612385565b105b15612aa95760009050612ade565b6000612ac7603c54612ab9611d73565b610dc190919063ffffffff16565b9050612ada612ad4610cc5565b82612ae1565b9150505b90565b6000818310612af05781612af2565b825b905092915050565b600080831415612b0d5760009050612b64565b6000828402905082848281612b1e57fe5b0414612b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5690614473565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff1615612bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb190614533565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c21906142f3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190614633565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0190614613565b60405180910390fd5b60008711612d4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4490614373565b60405180910390fd5b6000861415612d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d88906144b3565b60405180910390fd5b848610612dd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dca90614253565b60405180910390fd5b6001841015612e17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0e90614453565b60405180910390fd5b60006002811115612e2457fe5b816002811115612e3057fe5b1415612e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e6890614273565b60405180910390fd5b848310612eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eaa906145b3565b60405180910390fd5b848210612ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eec90614233565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612f198a61280b565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612fe357fe5b021790555050505050505050505050565b606082471015613039576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161303090614353565b60405180910390fd5b613042856131d0565b613081576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613078906144f3565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516130ab91906140c6565b60006040518083038185875af1925050503d80600081146130e8576040519150601f19603f3d011682016040523d82523d6000602084013e6130ed565b606091505b50915091506130fd8282866131e3565b92505050949350505050565b606061316b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166127179092919063ffffffff16565b90506000815111156131cb578080602001905181019061318b9190613539565b6131ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131c1906145d3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b606083156131f357829050613243565b6000835111156132065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323a91906141d1565b60405180910390fd5b9392505050565b6000813590506132598161486a565b92915050565b60008151905061326e8161486a565b92915050565b600082601f83011261328557600080fd5b8151613298613293826146bf565b61468e565b915081818352602084019350602081019050838560208402820111156132bd57600080fd5b60005b838110156132ed57816132d3888261325f565b8452602084019350602083019250506001810190506132c0565b5050505092915050565b60008151905061330681614881565b92915050565b60008135905061331b81614898565b92915050565b600060c0828403121561333357600080fd5b81905092915050565b60008135905061334b816148a8565b92915050565b600081519050613360816148a8565b92915050565b60006020828403121561337857600080fd5b60006133868482850161324a565b91505092915050565b6000602082840312156133a157600080fd5b60006133af8482850161325f565b91505092915050565b60008060008060008060008060008060006101608c8e0312156133da57600080fd5b60006133e88e828f0161324a565b9b505060206133f98e828f0161324a565b9a5050604061340a8e828f0161324a565b995050606061341b8e828f0161324a565b985050608061342c8e828f0161333c565b97505060a061343d8e828f0161333c565b96505060c061344e8e828f0161333c565b95505060e061345f8e828f0161333c565b9450506101006134718e828f0161333c565b9350506101206134838e828f0161333c565b9250506101406134958e828f0161330c565b9150509295989b509295989b9093969950565b600080600061010084860312156134be57600080fd5b60006134cc8682870161324a565b93505060206134dd8682870161324a565b92505060406134ee86828701613321565b9150509250925092565b60006020828403121561350a57600080fd5b600082015167ffffffffffffffff81111561352457600080fd5b61353084828501613274565b91505092915050565b60006020828403121561354b57600080fd5b6000613559848285016132f7565b91505092915050565b60006020828403121561357457600080fd5b60006135828482850161333c565b91505092915050565b60006020828403121561359d57600080fd5b60006135ab84828501613351565b91505092915050565b6135bd8161471d565b82525050565b6135cc8161472f565b82525050565b6135db8161473b565b82525050565b60006135ec826146eb565b6135f68185614701565b9350613606818560208601614810565b80840191505092915050565b61361b816147a4565b82525050565b61362a816147c8565b82525050565b613639816147ec565b82525050565b613648816147fe565b82525050565b6000613659826146f6565b613663818561470c565b9350613673818560208601614810565b61367c81614845565b840191505092915050565b600061369460088361470c565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b60006136d4601b8361470c565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b600061371460228361470c565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061377a60158361470c565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b60006137ba601e8361470c565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006137fa60268361470c565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613860601b8361470c565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006138a0601c8361470c565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006138e060148361470c565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613920601f8361470c565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613960601e8361470c565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006139a060268361470c565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a06601d8361470c565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b6000613a46601a8361470c565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b6000613a8660118361470c565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b6000613ac660138361470c565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b6000613b06601a8361470c565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b6000613b4660158361470c565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613b8660298361470c565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bec601f8361470c565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b6000613c2c60218361470c565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c9260208361470c565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613cd260168361470c565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613d1260158361470c565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613d52601d8361470c565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613d9260248361470c565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df860138361470c565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613e3860198361470c565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613e7860178361470c565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613eb860058361470c565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613ef8602a8361470c565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613f5e602a8361470c565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fc4601e8361470c565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b600061400460148361470c565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000614044601a8361470c565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000614084600f8361470c565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b6140c08161479a565b82525050565b60006140d282846135e1565b915081905092915050565b60006020820190506140f260008301846135b4565b92915050565b600060408201905061410d60008301856135b4565b61411a602083018461363f565b9392505050565b600060408201905061413660008301856135b4565b61414360208301846140b7565b9392505050565b600060208201905061415f60008301846135c3565b92915050565b600060208201905061417a60008301846135d2565b92915050565b60006020820190506141956000830184613612565b92915050565b60006020820190506141b06000830184613621565b92915050565b60006020820190506141cb6000830184613630565b92915050565b600060208201905081810360008301526141eb818461364e565b905092915050565b6000602082019050818103600083015261420c81613687565b9050919050565b6000602082019050818103600083015261422c816136c7565b9050919050565b6000602082019050818103600083015261424c81613707565b9050919050565b6000602082019050818103600083015261426c8161376d565b9050919050565b6000602082019050818103600083015261428c816137ad565b9050919050565b600060208201905081810360008301526142ac816137ed565b9050919050565b600060208201905081810360008301526142cc81613853565b9050919050565b600060208201905081810360008301526142ec81613893565b9050919050565b6000602082019050818103600083015261430c816138d3565b9050919050565b6000602082019050818103600083015261432c81613913565b9050919050565b6000602082019050818103600083015261434c81613953565b9050919050565b6000602082019050818103600083015261436c81613993565b9050919050565b6000602082019050818103600083015261438c816139f9565b9050919050565b600060208201905081810360008301526143ac81613a39565b9050919050565b600060208201905081810360008301526143cc81613a79565b9050919050565b600060208201905081810360008301526143ec81613ab9565b9050919050565b6000602082019050818103600083015261440c81613af9565b9050919050565b6000602082019050818103600083015261442c81613b39565b9050919050565b6000602082019050818103600083015261444c81613b79565b9050919050565b6000602082019050818103600083015261446c81613bdf565b9050919050565b6000602082019050818103600083015261448c81613c1f565b9050919050565b600060208201905081810360008301526144ac81613c85565b9050919050565b600060208201905081810360008301526144cc81613cc5565b9050919050565b600060208201905081810360008301526144ec81613d05565b9050919050565b6000602082019050818103600083015261450c81613d45565b9050919050565b6000602082019050818103600083015261452c81613d85565b9050919050565b6000602082019050818103600083015261454c81613deb565b9050919050565b6000602082019050818103600083015261456c81613e2b565b9050919050565b6000602082019050818103600083015261458c81613e6b565b9050919050565b600060208201905081810360008301526145ac81613eab565b9050919050565b600060208201905081810360008301526145cc81613eeb565b9050919050565b600060208201905081810360008301526145ec81613f51565b9050919050565b6000602082019050818103600083015261460c81613fb7565b9050919050565b6000602082019050818103600083015261462c81613ff7565b9050919050565b6000602082019050818103600083015261464c81614037565b9050919050565b6000602082019050818103600083015261466c81614077565b9050919050565b600060208201905061468860008301846140b7565b92915050565b6000604051905081810181811067ffffffffffffffff821117156146b5576146b4614843565b5b8060405250919050565b600067ffffffffffffffff8211156146da576146d9614843565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006147288261477a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061477582614856565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006147af826147b6565b9050919050565b60006147c18261477a565b9050919050565b60006147d3826147da565b9050919050565b60006147e58261477a565b9050919050565b60006147f782614767565b9050919050565b60006148098261479a565b9050919050565b60005b8381101561482e578082015181840152602081019050614813565b8381111561483d576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061486757614866614843565b5b50565b6148738161471d565b811461487e57600080fd5b50565b61488a8161472f565b811461489557600080fd5b50565b600381106148a557600080fd5b50565b6148b18161479a565b81146148bc57600080fd5b5056fea2646970667358221220b518abe45075b1a754063c65b10410a7c177459a73d10704d7ef06453ab5c8d464736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102605760003560e01c80637bdf05af11610144578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610bc7578063e8dda6f514610bf0578063e97d87d514610c1b578063ebbab99214610c46578063f2fde38b14610c71578063fc0c546a14610c9a576102a0565b8063bc0163c114610af4578063bd896dcb14610b1f578063ce845d1d14610b48578063d0ebdbe714610b73578063d18e81b314610b9c576102a0565b80638da5cb5b116101085780638da5cb5b14610a0857806391f7cfb914610a33578063a4caeb4214610a5e578063b0d1818c14610a89578063b470aade14610ab2578063b6549f7514610add576102a0565b80637bdf05af1461095957806386d00e021461098457806386d1a69f146109af578063872a7810146109c65780638a5bdf5c146109f1576102a0565b806338af3eed116101dd578063481c6a75116101a1578063481c6a751461087f5780635051a5ec146108aa5780635b940081146108d557806360e7994414610900578063715018a61461091757806378e979251461092e576102a0565b806338af3eed146107a8578063392e53cd146107d3578063398057a3146107fe57806344b1231f1461082957806345d30a1714610854576102a0565b806320dc203d1161022457806320dc203d146106e75780632a627814146107105780632bc9ed02146107275780633197cbb61461075257806337aeb0861461077d576102a0565b8063029c6c9f14610624578063060406181461064f5780630b80f7771461067a5780630dff24d5146106915780630fb5a6b4146106bc576102a0565b366102a0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610297906141f3565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610330576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610327906143d3565b60405180910390fd5b60003414610373576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161036a90614213565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103f49190614165565b60206040518083038186803b15801561040c57600080fd5b505afa158015610420573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610444919061338f565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104ad906144d3565b60405180910390fd5b60006104c0610cc5565b9050610511826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d77565b506001600281111561051f57fe5b603b60009054906101000a900460ff16600281111561053a57fe5b141561062057600061054a610cc5565b90508181101561058c5760006105698284610dc190919063ffffffff16565b905061058081603f54610e1190919063ffffffff16565b603f81905550506105d2565b60006105a18383610dc190919063ffffffff16565b9050603f548110156105c7576105c281603f54610dc190919063ffffffff16565b6105ca565b60005b603f81905550505b6105da610e66565b603f54111561061e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061590614433565b60405180910390fd5b505b5050005b34801561063057600080fd5b50610639610ed5565b6040516106469190614673565b60405180910390f35b34801561065b57600080fd5b50610664610ef3565b6040516106719190614673565b60405180910390f35b34801561068657600080fd5b5061068f610f2e565b005b34801561069d57600080fd5b506106a661109b565b6040516106b39190614673565b60405180910390f35b3480156106c857600080fd5b506106d16110e2565b6040516106de9190614673565b60405180910390f35b3480156106f357600080fd5b5061070e600480360381019061070991906134a8565b611100565b005b34801561071c57600080fd5b5061072561129b565b005b34801561073357600080fd5b5061073c611500565b604051610749919061414a565b60405180910390f35b34801561075e57600080fd5b50610767611513565b6040516107749190614673565b60405180910390f35b34801561078957600080fd5b50610792611519565b60405161079f9190614673565b60405180910390f35b3480156107b457600080fd5b506107bd61151f565b6040516107ca91906140dd565b60405180910390f35b3480156107df57600080fd5b506107e8611545565b6040516107f5919061414a565b60405180910390f35b34801561080a57600080fd5b50610813611558565b6040516108209190614673565b60405180910390f35b34801561083557600080fd5b5061083e610e66565b60405161084b9190614673565b60405180910390f35b34801561086057600080fd5b5061086961155e565b6040516108769190614673565b60405180910390f35b34801561088b57600080fd5b50610894611564565b6040516108a1919061419b565b60405180910390f35b3480156108b657600080fd5b506108bf61158a565b6040516108cc919061414a565b60405180910390f35b3480156108e157600080fd5b506108ea61159d565b6040516108f79190614673565b60405180910390f35b34801561090c57600080fd5b506109156116a8565b005b34801561092357600080fd5b5061092c6118ee565b005b34801561093a57600080fd5b50610943611a3a565b6040516109509190614673565b60405180910390f35b34801561096557600080fd5b5061096e611a40565b60405161097b9190614673565b60405180910390f35b34801561099057600080fd5b50610999611a7c565b6040516109a69190614673565b60405180910390f35b3480156109bb57600080fd5b506109c4611a82565b005b3480156109d257600080fd5b506109db611c5e565b6040516109e891906141b6565b60405180910390f35b3480156109fd57600080fd5b50610a06611c71565b005b348015610a1457600080fd5b50610a1d611d4a565b604051610a2a91906140dd565b60405180910390f35b348015610a3f57600080fd5b50610a48611d73565b604051610a559190614673565b60405180910390f35b348015610a6a57600080fd5b50610a73611dd1565b604051610a809190614673565b60405180910390f35b348015610a9557600080fd5b50610ab06004803603810190610aab9190613562565b611dd7565b005b348015610abe57600080fd5b50610ac7611fd6565b604051610ad49190614673565b60405180910390f35b348015610ae957600080fd5b50610af2611ff9565b005b348015610b0057600080fd5b50610b09612291565b604051610b169190614673565b60405180910390f35b348015610b2b57600080fd5b50610b466004803603810190610b4191906133b8565b6122c3565b005b348015610b5457600080fd5b50610b5d610cc5565b604051610b6a9190614673565b60405180910390f35b348015610b7f57600080fd5b50610b9a6004803603810190610b959190613366565b6122eb565b005b348015610ba857600080fd5b50610bb1612385565b604051610bbe9190614673565b60405180910390f35b348015610bd357600080fd5b50610bee6004803603810190610be99190613366565b61238d565b005b348015610bfc57600080fd5b50610c05612508565b604051610c129190614673565b60405180910390f35b348015610c2757600080fd5b50610c3061250e565b604051610c3d9190614673565b60405180910390f35b348015610c5257600080fd5b50610c5b612514565b604051610c689190614673565b60405180910390f35b348015610c7d57600080fd5b50610c986004803603810190610c939190613366565b612536565b005b348015610ca657600080fd5b50610caf6126f1565b604051610cbc9190614180565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d2291906140dd565b60206040518083038186803b158015610d3a57600080fd5b505afa158015610d4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d72919061358b565b905090565b6060610db983836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612717565b905092915050565b600082821115610e06576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dfd90614333565b60405180910390fd5b818303905092915050565b600080828401905083811015610e5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e53906142b3565b60405180910390fd5b8091505092915050565b6000600280811115610e7457fe5b603b60009054906101000a900460ff166002811115610e8f57fe5b1415610e9f576035549050610ed2565b6000603a54118015610eb95750603a54610eb7612385565b105b15610ec75760009050610ed2565b610ecf611d73565b90505b90565b6000610eee60385460355461272f90919063ffffffff16565b905090565b6000610f296001610f1b610f05611fd6565b610f0d611a40565b61272f90919063ffffffff16565b610e1190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fb390614493565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514611012576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100990614313565b60405180910390fd5b61106d61101d611d4a565b611025610cc5565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b6000806110a6610cc5565b905060006110b2612291565b9050808211156110d8576110cf8183610dc190919063ffffffff16565b925050506110df565b6000925050505b90565b60006110fb603654603754610dc190919063ffffffff16565b905090565b603b60029054906101000a900460ff1615611150576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114790614533565b60405180910390fd5b6001603b60026101000a81548160ff0219169083151502179055506111868160200160208101906111819190613366565b61280b565b8060400160208101906111999190613366565b603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806060013560358190555080608001356036819055508060a0013560378190555060016038819055506001603b60036101000a81548160ff0219169083151502179055508060a001356039819055506002603b60006101000a81548160ff0219169083600281111561128857fe5b0217905550611296836128a9565b505050565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461132b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161132290614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561139557600080fd5b505afa1580156113a9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906113d291906134f8565b905060005b81518110156114d057603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061142a57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b8152600401611470929190614121565b602060405180830381600087803b15801561148a57600080fd5b505af115801561149e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c29190613539565b5080806001019150506113d7565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156115ab57fe5b603b60009054906101000a900460ff1660028111156115c657fe5b14156115db576115d4612a27565b90506116a5565b60006039541180156115f557506039546115f3612385565b105b1561160357600090506116a5565b6001600281111561161057fe5b603b60009054906101000a900460ff16600281111561162b57fe5b14801561163a57506000603a54115b801561164e5750603a5461164c612385565b105b1561165c57600090506116a5565b600061168e603f54611680603c54611672611d73565b610dc190919063ffffffff16565b610dc190919063ffffffff16565b90506116a161169b610cc5565b82612ae1565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161172f90614593565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156117a257600080fd5b505afa1580156117b6573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f820116820180604052508101906117df91906134f8565b905060005b81518110156118be57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061183757fe5b602002602001015160006040518363ffffffff1660e01b815260040161185e9291906140f8565b602060405180830381600087803b15801561187857600080fd5b505af115801561188c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118b09190613539565b5080806001019150506117e4565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461197c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161197390614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b600080611a4b612385565b90506036548111611a60576000915050611a79565b611a7560365482610dc190919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b12576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b0990614593565b60405180910390fd5b6000611b1c61159d565b905060008111611b61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b58906145f3565b60405180910390fd5b611b7681603c54610e1190919063ffffffff16565b603c81905550611beb603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611c539190614673565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890614593565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611d7e612385565b9050603654811015611d94576000915050611dce565b603754811115611da957603554915050611dce565b611dca611db4610ed5565b611dbc612514565b612afa90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611e67576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e5e90614593565b60405180910390fd5b60008111611eaa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ea190614413565b60405180910390fd5b80611eb361109b565b1015611ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eeb90614513565b60405180910390fd5b611f63603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611fcb9190614673565b60405180910390a250565b6000611ff4603854611fe66110e2565b61272f90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612087576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207e90614493565b60405180910390fd5b6001600281111561209457fe5b603b60009054906101000a900460ff1660028111156120af57fe5b146120ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e690614553565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514612145576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161213c90614653565b60405180910390fd5b6000612163612152610e66565b603554610dc190919063ffffffff16565b9050600081116121a8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219f906142d3565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061221e6121d5611d4a565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166127859092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516122869190614673565b60405180910390a250565b60006122be603d546122b0603c54603554610dc190919063ffffffff16565b610dc190919063ffffffff16565b905090565b6122d58a8a8a8a8a8a8a8a8a8a612b6a565b6122de8b6128a9565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612379576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237090614493565b60405180910390fd5b612382816128a9565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461241d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161241490614593565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561248d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612484906143b3565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d816040516124fd91906140dd565b60405180910390a150565b603f5481565b60395481565b60006125316001612523610ef3565b610dc190919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146125c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125bb90614493565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612634576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161262b90614293565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606127268484600085612ff4565b90509392505050565b6000808211612773576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276a90614393565b60405180910390fd5b81838161277c57fe5b04905092915050565b6128068363a9059cbb60e01b84846040516024016127a4929190614121565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613109565b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612919576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161291090614573565b60405180910390fd5b612922816131d0565b612961576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612958906143f3565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b600080603954118015612a425750603954612a40612385565b105b15612a505760009050612ade565b60016002811115612a5d57fe5b603b60009054906101000a900460ff166002811115612a7857fe5b148015612a8757506000603a54115b8015612a9b5750603a54612a99612385565b105b15612aa95760009050612ade565b6000612ac7603c54612ab9611d73565b610dc190919063ffffffff16565b9050612ada612ad4610cc5565b82612ae1565b9150505b90565b6000818310612af05781612af2565b825b905092915050565b600080831415612b0d5760009050612b64565b6000828402905082848281612b1e57fe5b0414612b5f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b5690614473565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff1615612bba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb190614533565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612c2a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c21906142f3565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612c9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c9190614633565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612d0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d0190614613565b60405180910390fd5b60008711612d4d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d4490614373565b60405180910390fd5b6000861415612d91576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d88906144b3565b60405180910390fd5b848610612dd3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dca90614253565b60405180910390fd5b6001841015612e17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0e90614453565b60405180910390fd5b60006002811115612e2457fe5b816002811115612e3057fe5b1415612e71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e6890614273565b60405180910390fd5b848310612eb3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eaa906145b3565b60405180910390fd5b848210612ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612eec90614233565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612f198a61280b565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612fe357fe5b021790555050505050505050505050565b606082471015613039576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161303090614353565b60405180910390fd5b613042856131d0565b613081576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613078906144f3565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516130ab91906140c6565b60006040518083038185875af1925050503d80600081146130e8576040519150601f19603f3d011682016040523d82523d6000602084013e6130ed565b606091505b50915091506130fd8282866131e3565b92505050949350505050565b606061316b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166127179092919063ffffffff16565b90506000815111156131cb578080602001905181019061318b9190613539565b6131ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131c1906145d3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b606083156131f357829050613243565b6000835111156132065782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161323a91906141d1565b60405180910390fd5b9392505050565b6000813590506132598161486a565b92915050565b60008151905061326e8161486a565b92915050565b600082601f83011261328557600080fd5b8151613298613293826146bf565b61468e565b915081818352602084019350602081019050838560208402820111156132bd57600080fd5b60005b838110156132ed57816132d3888261325f565b8452602084019350602083019250506001810190506132c0565b5050505092915050565b60008151905061330681614881565b92915050565b60008135905061331b81614898565b92915050565b600060c0828403121561333357600080fd5b81905092915050565b60008135905061334b816148a8565b92915050565b600081519050613360816148a8565b92915050565b60006020828403121561337857600080fd5b60006133868482850161324a565b91505092915050565b6000602082840312156133a157600080fd5b60006133af8482850161325f565b91505092915050565b60008060008060008060008060008060006101608c8e0312156133da57600080fd5b60006133e88e828f0161324a565b9b505060206133f98e828f0161324a565b9a5050604061340a8e828f0161324a565b995050606061341b8e828f0161324a565b985050608061342c8e828f0161333c565b97505060a061343d8e828f0161333c565b96505060c061344e8e828f0161333c565b95505060e061345f8e828f0161333c565b9450506101006134718e828f0161333c565b9350506101206134838e828f0161333c565b9250506101406134958e828f0161330c565b9150509295989b509295989b9093969950565b600080600061010084860312156134be57600080fd5b60006134cc8682870161324a565b93505060206134dd8682870161324a565b92505060406134ee86828701613321565b9150509250925092565b60006020828403121561350a57600080fd5b600082015167ffffffffffffffff81111561352457600080fd5b61353084828501613274565b91505092915050565b60006020828403121561354b57600080fd5b6000613559848285016132f7565b91505092915050565b60006020828403121561357457600080fd5b60006135828482850161333c565b91505092915050565b60006020828403121561359d57600080fd5b60006135ab84828501613351565b91505092915050565b6135bd8161471d565b82525050565b6135cc8161472f565b82525050565b6135db8161473b565b82525050565b60006135ec826146eb565b6135f68185614701565b9350613606818560208601614810565b80840191505092915050565b61361b816147a4565b82525050565b61362a816147c8565b82525050565b613639816147ec565b82525050565b613648816147fe565b82525050565b6000613659826146f6565b613663818561470c565b9350613673818560208601614810565b61367c81614845565b840191505092915050565b600061369460088361470c565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b60006136d4601b8361470c565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b600061371460228361470c565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061377a60158361470c565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b60006137ba601e8361470c565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006137fa60268361470c565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613860601b8361470c565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b60006138a0601c8361470c565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006138e060148361470c565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613920601f8361470c565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613960601e8361470c565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006139a060268361470c565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a06601d8361470c565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b6000613a46601a8361470c565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b6000613a8660118361470c565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b6000613ac660138361470c565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b6000613b06601a8361470c565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b6000613b4660158361470c565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000613b8660298361470c565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bec601f8361470c565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b6000613c2c60218361470c565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613c9260208361470c565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613cd260168361470c565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613d1260158361470c565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613d52601d8361470c565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613d9260248361470c565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613df860138361470c565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613e3860198361470c565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613e7860178361470c565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613eb860058361470c565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613ef8602a8361470c565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613f5e602a8361470c565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613fc4601e8361470c565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b600061400460148361470c565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000614044601a8361470c565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000614084600f8361470c565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b6140c08161479a565b82525050565b60006140d282846135e1565b915081905092915050565b60006020820190506140f260008301846135b4565b92915050565b600060408201905061410d60008301856135b4565b61411a602083018461363f565b9392505050565b600060408201905061413660008301856135b4565b61414360208301846140b7565b9392505050565b600060208201905061415f60008301846135c3565b92915050565b600060208201905061417a60008301846135d2565b92915050565b60006020820190506141956000830184613612565b92915050565b60006020820190506141b06000830184613621565b92915050565b60006020820190506141cb6000830184613630565b92915050565b600060208201905081810360008301526141eb818461364e565b905092915050565b6000602082019050818103600083015261420c81613687565b9050919050565b6000602082019050818103600083015261422c816136c7565b9050919050565b6000602082019050818103600083015261424c81613707565b9050919050565b6000602082019050818103600083015261426c8161376d565b9050919050565b6000602082019050818103600083015261428c816137ad565b9050919050565b600060208201905081810360008301526142ac816137ed565b9050919050565b600060208201905081810360008301526142cc81613853565b9050919050565b600060208201905081810360008301526142ec81613893565b9050919050565b6000602082019050818103600083015261430c816138d3565b9050919050565b6000602082019050818103600083015261432c81613913565b9050919050565b6000602082019050818103600083015261434c81613953565b9050919050565b6000602082019050818103600083015261436c81613993565b9050919050565b6000602082019050818103600083015261438c816139f9565b9050919050565b600060208201905081810360008301526143ac81613a39565b9050919050565b600060208201905081810360008301526143cc81613a79565b9050919050565b600060208201905081810360008301526143ec81613ab9565b9050919050565b6000602082019050818103600083015261440c81613af9565b9050919050565b6000602082019050818103600083015261442c81613b39565b9050919050565b6000602082019050818103600083015261444c81613b79565b9050919050565b6000602082019050818103600083015261446c81613bdf565b9050919050565b6000602082019050818103600083015261448c81613c1f565b9050919050565b600060208201905081810360008301526144ac81613c85565b9050919050565b600060208201905081810360008301526144cc81613cc5565b9050919050565b600060208201905081810360008301526144ec81613d05565b9050919050565b6000602082019050818103600083015261450c81613d45565b9050919050565b6000602082019050818103600083015261452c81613d85565b9050919050565b6000602082019050818103600083015261454c81613deb565b9050919050565b6000602082019050818103600083015261456c81613e2b565b9050919050565b6000602082019050818103600083015261458c81613e6b565b9050919050565b600060208201905081810360008301526145ac81613eab565b9050919050565b600060208201905081810360008301526145cc81613eeb565b9050919050565b600060208201905081810360008301526145ec81613f51565b9050919050565b6000602082019050818103600083015261460c81613fb7565b9050919050565b6000602082019050818103600083015261462c81613ff7565b9050919050565b6000602082019050818103600083015261464c81614037565b9050919050565b6000602082019050818103600083015261466c81614077565b9050919050565b600060208201905061468860008301846140b7565b92915050565b6000604051905081810181811067ffffffffffffffff821117156146b5576146b4614843565b5b8060405250919050565b600067ffffffffffffffff8211156146da576146d9614843565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006147288261477a565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061477582614856565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006147af826147b6565b9050919050565b60006147c18261477a565b9050919050565b60006147d3826147da565b9050919050565b60006147e58261477a565b9050919050565b60006147f782614767565b9050919050565b60006148098261479a565b9050919050565b60005b8381101561482e578082015181840152602081019050614813565b8381111561483d576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061486757614866614843565b5b50565b6148738161471d565b811461487e57600080fd5b50565b61488a8161472f565b811461489557600080fd5b50565b600381106148a557600080fd5b50565b6148b18161479a565b81146148bc57600080fd5b5056fea2646970667358221220b518abe45075b1a754063c65b10410a7c177459a73d10704d7ef06453ab5c8d464736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "L2GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. This L2 variant includes a special initializer so that it can be created from a wallet's data received from L1. These transferred wallets will not allow releasing funds in L2 until the end of the vesting timeline, but they can allow withdrawing funds back to L1 using the L2GraphTokenLockTransferTool contract. Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1, so releasing surplus tokens might also only be possible by bridging tokens back to L1. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6817, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 6822, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 3244, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "51", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 3246, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "52", + "type": "t_address" + }, + { + "astId": 3248, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "53", + "type": "t_uint256" + }, + { + "astId": 3250, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "54", + "type": "t_uint256" + }, + { + "astId": 3252, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "55", + "type": "t_uint256" + }, + { + "astId": 3254, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 3256, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "57", + "type": "t_uint256" + }, + { + "astId": 3258, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "58", + "type": "t_uint256" + }, + { + "astId": 3260, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "59", + "type": "t_enum(Revocability)5096" + }, + { + "astId": 3262, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3264, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3266, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3268, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "60", + "type": "t_uint256" + }, + { + "astId": 3270, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "61", + "type": "t_uint256" + }, + { + "astId": 4692, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "62", + "type": "t_contract(IGraphTokenLockManager)5278" + }, + { + "astId": 4694, + "contract": "contracts/L2GraphTokenLockWallet.sol:L2GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "63", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)5278": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)5096": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/arbitrum-sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json b/packages/token-distribution/deployments/arbitrum-sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json new file mode 100644 index 000000000..e7a4b87c0 --- /dev/null +++ b/packages/token-distribution/deployments/arbitrum-sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json @@ -0,0 +1,152 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMathUpgradeable {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/arbitrum/ITokenGateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2020, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\ninterface ITokenGateway {\n /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated\n // event OutboundTransferInitiated(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized\n // event InboundTransferFinalized(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n function outboundTransfer(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n function finalizeInboundTransfer(\n address _token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n\n /**\n * @notice Calculate the address used when bridging an ERC20 token\n * @dev the L1 and L2 address oracles may not always be in sync.\n * For example, a custom token may have been registered but not deployed or the contract self destructed.\n * @param l1ERC20 address of L1 token\n * @return L2 address of a bridged ERC20 token\n */\n function calculateL2TokenAddress(address l1ERC20) external view returns (address);\n}\n" + }, + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n OwnableInitializable._initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 internal _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSelector(\n GraphTokenLockWallet.initialize.selector,\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(\n string[] calldata _signatures,\n address[] calldata _targets\n ) external override onlyOwner {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n *\n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n OwnableInitializable._initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) internal {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe because we are using the max uint256 value\n token.approve(dstList[i], type(uint256).max);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe cause we're using 0 as the amount\n token.approve(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n require(msg.value == 0, \"ETH transfers not supported\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n\n /**\n * @notice Receive function that always reverts.\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\n */\n receive() external payable {\n revert(\"Bad call\");\n }\n}\n" + }, + "contracts/ICallhookReceiver.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\n\n/**\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\n * be allowlisted by the governor, but also implement this interface that contains\n * the function that will actually be called by the L2GraphTokenGateway.\n */\npragma solidity ^0.7.3;\n\ninterface ICallhookReceiver {\n /**\n * @notice Receive tokens with a callhook from the bridge\n * @param _from Token sender in L1\n * @param _amount Amount of tokens that were transferred\n * @param _data ABI-encoded callhook data\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/L1GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { AddressUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { MinimalProxyFactory } from \"./MinimalProxyFactory.sol\";\nimport { IGraphTokenLock } from \"./IGraphTokenLock.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { SafeMathUpgradeable } from \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @title L1GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from GraphTokenLockWallets\n * to a counterpart on L2. It is deployed on L1 and will send the GRT through\n * the L1GraphTokenGateway with a callhook to the L2GraphTokenLockManager, including\n * data to create a L2GraphTokenLockWallet on L2.\n *\n * Note that the L2GraphTokenLockWallet will not allow releasing any GRT until the end of\n * the vesting timeline, but will allow sending the GRT back to the L1 wallet.\n *\n * Beneficiaries for a GraphTokenLockWallet can perform the depositToL2Locked call\n * as many times as they want, and the GRT will be sent to the same L2GraphTokenLockWallet.\n *\n * Since all retryable tickets to send transactions to L2 require ETH for gas, this\n * contract also allows users to deposit ETH to be used for gas on L2, both for\n * the depositToL2Locked calls and for the transfer tools in the Staking contract for\n * The Graph.\n *\n * See GIP-0046 for more details: https://forum.thegraph.com/t/4023\n */\ncontract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, MinimalProxyFactory {\n using SafeMathUpgradeable for uint256;\n\n /// Address of the L1 GRT token contract\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses\n address public immutable l2Implementation;\n /// Address of the L1GraphTokenGateway contract\n ITokenGateway public immutable l1Gateway;\n /// Address of the Staking contract, used to pull ETH for L2 ticket gas\n address payable public immutable staking;\n /// L2 lock manager for each L1 lock manager.\n /// L1 GraphTokenLockManager => L2GraphTokenLockManager\n mapping(address => address) public l2LockManager;\n /// L2 wallet owner for each L1 wallet owner.\n /// L1 wallet owner => L2 wallet owner\n mapping(address => address) public l2WalletOwner;\n /// L2 wallet address for each L1 wallet address.\n /// L1 wallet => L2 wallet\n mapping(address => address) public l2WalletAddress;\n /// ETH balance from each token lock, used to pay for L2 gas:\n /// L1 wallet address => ETH balance\n mapping(address => uint256) public tokenLockETHBalances;\n /// L2 beneficiary corresponding to each L1 wallet address.\n /// L1 wallet => L2 beneficiary\n mapping(address => address) public l2Beneficiary;\n /// Indicates whether an L2 wallet address for a wallet\n /// has been set manually, in which case it can't call depositToL2Locked.\n /// L1 wallet => bool\n mapping(address => bool) public l2WalletAddressSetManually;\n\n /// @dev Emitted when the L2 lock manager for an L1 lock manager is set\n event L2LockManagerSet(address indexed l1LockManager, address indexed l2LockManager);\n /// @dev Emitted when the L2 wallet owner for an L1 wallet owner is set\n event L2WalletOwnerSet(address indexed l1WalletOwner, address indexed l2WalletOwner);\n /// @dev Emitted when GRT is sent to L2 from a token lock\n event LockedFundsSentToL2(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l1LockManager,\n address l2LockManager,\n uint256 amount\n );\n /// @dev Emitted when an L2 wallet address is set for an L1 wallet\n event L2WalletAddressSet(address indexed l1Wallet, address indexed l2Wallet);\n /// @dev Emitted when ETH is deposited to a token lock's account\n event ETHDeposited(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when ETH is withdrawn from a token lock's account\n event ETHWithdrawn(address indexed tokenLock, address indexed destination, uint256 amount);\n /// @dev Emitted when ETH is pulled from a token lock's account by Staking or this tool to pay for an L2 ticket\n event ETHPulled(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when the L2 beneficiary for a partially vested L1 lock is set\n event L2BeneficiarySet(address indexed l1Wallet, address indexed l2Beneficiary);\n\n /**\n * @notice Construct a new L1GraphTokenLockTransferTool contract\n * @dev The deployer of the contract will become its owner.\n * Note this contract is meant to be deployed behind a transparent proxy,\n * so this will run at the implementation's storage context; it will set\n * immutable variables and make the implementation be owned by the deployer.\n * @param _graphToken Address of the L1 GRT token contract\n * @param _l2Implementation Address of the L2GraphTokenLockWallet implementation in L2\n * @param _l1Gateway Address of the L1GraphTokenGateway contract\n * @param _staking Address of the Staking contract\n */\n constructor(\n IERC20 _graphToken,\n address _l2Implementation,\n ITokenGateway _l1Gateway,\n address payable _staking\n ) initializer {\n OwnableInitializable._initialize(msg.sender);\n graphToken = _graphToken;\n l2Implementation = _l2Implementation;\n l1Gateway = _l1Gateway;\n staking = _staking;\n }\n\n /**\n * @notice Initialize the L1GraphTokenLockTransferTool contract\n * @dev This function will run in the proxy's storage context, so it will\n * set the owner of the proxy contract which can be different from the implementation owner.\n * @param _owner Address of the owner of the L1GraphTokenLockTransferTool contract\n */\n function initialize(address _owner) external initializer {\n OwnableInitializable._initialize(_owner);\n }\n\n /**\n * @notice Set the L2 lock manager that corresponds to an L1 lock manager\n * @param _l1LockManager Address of the L1 lock manager\n * @param _l2LockManager Address of the L2 lock manager (in L2)\n */\n function setL2LockManager(address _l1LockManager, address _l2LockManager) external onlyOwner {\n l2LockManager[_l1LockManager] = _l2LockManager;\n emit L2LockManagerSet(_l1LockManager, _l2LockManager);\n }\n\n /**\n * @notice Set the L2 wallet owner that corresponds to an L1 wallet owner\n * @param _l1WalletOwner Address of the L1 wallet owner\n * @param _l2WalletOwner Address of the L2 wallet owner (in L2)\n */\n function setL2WalletOwner(address _l1WalletOwner, address _l2WalletOwner) external onlyOwner {\n l2WalletOwner[_l1WalletOwner] = _l2WalletOwner;\n emit L2WalletOwnerSet(_l1WalletOwner, _l2WalletOwner);\n }\n\n /**\n * @notice Deposit ETH on a token lock's account, to be used for L2 retryable ticket gas.\n * This function can be called by anyone, but the ETH will be credited to the token lock.\n * DO NOT try to call this through the token lock, as locks do not forward ETH value (and the\n * function call should not be allowlisted).\n * @param _tokenLock Address of the L1 GraphTokenLockWallet that will own the ETH\n */\n function depositETH(address _tokenLock) external payable {\n tokenLockETHBalances[_tokenLock] = tokenLockETHBalances[_tokenLock].add(msg.value);\n emit ETHDeposited(_tokenLock, msg.value);\n }\n\n /**\n * @notice Withdraw ETH from a token lock's account.\n * This function must be called from the token lock contract, but the destination\n * _must_ be a different address, as any ETH sent to the token lock would otherwise be\n * lost.\n * @param _destination Address to send the ETH\n * @param _amount Amount of ETH to send\n */\n function withdrawETH(address _destination, uint256 _amount) external {\n require(_amount > 0, \"INVALID_AMOUNT\");\n // We can't send eth to a token lock or it will be stuck\n require(msg.sender != _destination, \"INVALID_DESTINATION\");\n require(tokenLockETHBalances[msg.sender] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[msg.sender] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = payable(_destination).call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHWithdrawn(msg.sender, _destination, _amount);\n }\n\n /**\n * @notice Pull ETH from a token lock's account, to be used for L2 retryable ticket gas.\n * This can only be called by the Staking contract.\n * @param _tokenLock GraphTokenLockWallet that owns the ETH that will be debited\n * @param _amount Amount of ETH to pull\n */\n function pullETH(address _tokenLock, uint256 _amount) external {\n require(msg.sender == staking, \"ONLY_STAKING\");\n require(tokenLockETHBalances[_tokenLock] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[_tokenLock] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = staking.call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHPulled(_tokenLock, _amount);\n }\n\n /**\n * @notice Deposit GRT to L2, from a token lock in L1 to a token lock in L2.\n * If the token lock in L2 does not exist, it will be created when the message is received\n * by the L2GraphTokenLockManager.\n * Before calling this (which must be done through the token lock wallet), make sure\n * there is enough ETH in the token lock's account to cover the L2 retryable ticket gas.\n * Note that L2 submission fee and gas refunds will be lost.\n * You can add ETH to the token lock's account by calling depositETH().\n * Note that after calling this, you will NOT be able to use setL2WalletAddressManually() to\n * set an L2 wallet address, as the L2 wallet address will be set automatically when the\n * message is received by the L2GraphTokenLockManager.\n * @dev The gas parameters for L2 can be estimated using the Arbitrum SDK.\n * @param _amount Amount of GRT to deposit\n * @param _l2Beneficiary Address of the beneficiary for the token lock in L2. Must be the same for subsequent calls of this function, and not an L1 contract.\n * @param _maxGas Maximum gas to use for the L2 retryable ticket\n * @param _gasPriceBid Gas price to use for the L2 retryable ticket\n * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket\n */\n function depositToL2Locked(\n uint256 _amount,\n address _l2Beneficiary,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n uint256 _maxSubmissionCost\n ) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n require(wallet.revocable() != IGraphTokenLock.Revocability.Enabled, \"REVOCABLE\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n if (l2Beneficiary[msg.sender] == address(0)) {\n require(_l2Beneficiary != address(0), \"INVALID_BENEFICIARY_ZERO\");\n require(!AddressUpgradeable.isContract(_l2Beneficiary), \"INVALID_BENEFICIARY_CONTRACT\");\n l2Beneficiary[msg.sender] = _l2Beneficiary;\n emit L2BeneficiarySet(msg.sender, _l2Beneficiary);\n } else {\n require(l2Beneficiary[msg.sender] == _l2Beneficiary, \"INVALID_BENEFICIARY\");\n }\n\n uint256 expectedEth = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(tokenLockETHBalances[msg.sender] >= expectedEth, \"INSUFFICIENT_ETH_BALANCE\");\n tokenLockETHBalances[msg.sender] -= expectedEth;\n\n bytes memory encodedData;\n {\n address l2Owner = l2WalletOwner[wallet.owner()];\n require(l2Owner != address(0), \"L2_OWNER_NOT_SET\");\n // Extract all the storage variables from the GraphTokenLockWallet\n L2GraphTokenLockManager.TransferredWalletData memory data = L2GraphTokenLockManager.TransferredWalletData({\n l1Address: msg.sender,\n owner: l2Owner,\n beneficiary: l2Beneficiary[msg.sender],\n managedAmount: wallet.managedAmount(),\n startTime: wallet.startTime(),\n endTime: wallet.endTime()\n });\n encodedData = abi.encode(data);\n }\n\n if (l2WalletAddress[msg.sender] == address(0)) {\n require(wallet.endTime() >= block.timestamp, \"FULLY_VESTED_USE_MANUAL_ADDRESS\");\n address newAddress = getDeploymentAddress(keccak256(encodedData), l2Implementation, l2Manager);\n l2WalletAddress[msg.sender] = newAddress;\n emit L2WalletAddressSet(msg.sender, newAddress);\n } else {\n require(!l2WalletAddressSetManually[msg.sender], \"CANT_DEPOSIT_TO_MANUAL_ADDRESS\");\n }\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n\n // Send the tokens with a message through the L1GraphTokenGateway to the L2GraphTokenLockManager\n graphToken.approve(address(l1Gateway), _amount);\n {\n bytes memory transferData = abi.encode(_maxSubmissionCost, encodedData);\n l1Gateway.outboundTransfer{ value: expectedEth }(\n address(graphToken),\n l2Manager,\n _amount,\n _maxGas,\n _gasPriceBid,\n transferData\n );\n }\n emit ETHPulled(msg.sender, expectedEth);\n emit LockedFundsSentToL2(msg.sender, l2WalletAddress[msg.sender], l1Manager, l2Manager, _amount);\n }\n\n /**\n * @notice Manually set the L2 wallet address for a token lock in L1.\n * This will only work for token locks that have not been initialized in L2 yet, and\n * that are fully vested (endTime < current timestamp).\n * This address can then be used to send stake or delegation to L2 on the Staking contract.\n * After calling this, the vesting lock will NOT be allowed to use depositToL2Locked\n * to send GRT to L2, the beneficiary must withdraw the tokens and bridge them manually.\n * @param _l2Wallet Address of the L2 wallet\n */\n function setL2WalletAddressManually(address _l2Wallet) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n\n // Check that the wallet is fully vested\n require(wallet.endTime() < block.timestamp, \"NOT_FULLY_VESTED\");\n\n // Check that the wallet has not set an L2 wallet yet\n require(l2WalletAddress[msg.sender] == address(0), \"L2_WALLET_ALREADY_SET\");\n\n // Check that the L2 address is not zero\n require(_l2Wallet != address(0), \"ZERO_ADDRESS\");\n // Set the L2 wallet address\n l2WalletAddress[msg.sender] = _l2Wallet;\n l2WalletAddressSetManually[msg.sender] = true;\n emit L2WalletAddressSet(msg.sender, _l2Wallet);\n }\n}\n" + }, + "contracts/L2GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { ICallhookReceiver } from \"./ICallhookReceiver.sol\";\nimport { GraphTokenLockManager } from \"./GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\n\n/**\n * @title L2GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\n * the L2GraphTokenLockTransferTool contract.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\n using SafeERC20 for IERC20;\n\n /// @dev Struct to hold the data of a transferred wallet; this is\n /// the data that must be encoded in L1 to send a wallet to L2.\n struct TransferredWalletData {\n address l1Address;\n address owner;\n address beneficiary;\n uint256 managedAmount;\n uint256 startTime;\n uint256 endTime;\n }\n\n /// Address of the L2GraphTokenGateway\n address public immutable l2Gateway;\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\n address public immutable l1TransferTool;\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\n /// L1 address => L2 address\n mapping(address => address) public l1WalletToL2Wallet;\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\n /// L2 address => L1 address\n mapping(address => address) public l2WalletToL1Wallet;\n\n /// @dev Event emitted when a wallet is received and created from L1\n event TokenLockCreatedFromL1(\n address indexed contractAddress,\n bytes32 initHash,\n address indexed beneficiary,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n address indexed l1Address\n );\n\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\n /// had already been received or not)\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\n\n /**\n * @dev Checks that the sender is the L2GraphTokenGateway.\n */\n modifier onlyL2Gateway() {\n require(msg.sender == l2Gateway, \"ONLY_GATEWAY\");\n _;\n }\n\n /**\n * @notice Constructor for the L2GraphTokenLockManager contract.\n * @param _graphToken Address of the L2 GRT token contract\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\n */\n constructor(\n IERC20 _graphToken,\n address _masterCopy,\n address _l2Gateway,\n address _l1TransferTool\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\n l2Gateway = _l2Gateway;\n l1TransferTool = _l1TransferTool;\n }\n\n /**\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\n * the existing wallet if it does.\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\n * @param _amount Amount of tokens received\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\n require(_from == l1TransferTool, \"ONLY_TRANSFER_TOOL\");\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\n\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\n // If the wallet was already received, just send the tokens to the L2 address\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\n } else {\n // Create contract using a minimal proxy and call initializer\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _amount);\n\n emit TokenLockCreatedFromL1(\n contractAddress,\n initHash,\n walletData.beneficiary,\n walletData.managedAmount,\n walletData.startTime,\n walletData.endTime,\n walletData.l1Address\n );\n }\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\n }\n\n /**\n * @dev Deploy a token lock wallet with data received from L1\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\n * @param _walletData Data of the wallet to be created\n * @return Hash of the initialization calldata\n * @return Address of the created contract\n */\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\n bytes memory initializer = _encodeInitializer(_walletData);\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\n return (keccak256(initializer), contractAddress);\n }\n\n /**\n * @dev Encode the initializer for the token lock wallet received from L1\n * @param _walletData Data of the wallet to be created\n * @return Encoded initializer calldata, including the function signature\n */\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\n return\n abi.encodeWithSelector(\n L2GraphTokenLockWallet.initializeFromL1.selector,\n address(this),\n address(_token),\n _walletData\n );\n }\n}\n" + }, + "contracts/L2GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\n\n/**\n * @title L2GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from L2 token lock wallets\n * back to their L1 counterparts.\n */\ncontract L2GraphTokenLockTransferTool {\n /// Address of the L2 GRT token\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenGateway\n ITokenGateway public immutable l2Gateway;\n /// Address of the L1 GRT token (in L1, no aliasing)\n address public immutable l1GraphToken;\n\n /// @dev Emitted when GRT is sent to L1 from a token lock\n event LockedFundsSentToL1(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l2LockManager,\n uint256 amount\n );\n\n /**\n * @notice Constructor for the L2GraphTokenLockTransferTool contract\n * @dev Note the L2GraphTokenLockTransferTool can be deployed behind a proxy,\n * and the constructor for the implementation will only set some immutable\n * variables.\n * @param _graphToken Address of the L2 GRT token\n * @param _l2Gateway Address of the L2GraphTokenGateway\n * @param _l1GraphToken Address of the L1 GRT token (in L1, no aliasing)\n */\n constructor(IERC20 _graphToken, ITokenGateway _l2Gateway, address _l1GraphToken) {\n graphToken = _graphToken;\n l2Gateway = _l2Gateway;\n l1GraphToken = _l1GraphToken;\n }\n\n /**\n * @notice Withdraw GRT from an L2 token lock wallet to its L1 counterpart.\n * This function must be called from an L2GraphTokenLockWallet contract.\n * The GRT will be sent to L1 and must be claimed using the Arbitrum Outbox on L1\n * after the standard Arbitrum withdrawal period (7 days).\n * @param _amount Amount of GRT to withdraw\n */\n function withdrawToL1Locked(uint256 _amount) external {\n L2GraphTokenLockWallet wallet = L2GraphTokenLockWallet(msg.sender);\n L2GraphTokenLockManager manager = L2GraphTokenLockManager(address(wallet.manager()));\n require(address(manager) != address(0), \"INVALID_SENDER\");\n address l1Wallet = manager.l2WalletToL1Wallet(msg.sender);\n require(l1Wallet != address(0), \"NOT_L1_WALLET\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n graphToken.approve(address(l2Gateway), _amount);\n\n // Send the tokens through the L2GraphTokenGateway to the L1 wallet counterpart\n l2Gateway.outboundTransfer(l1GraphToken, l1Wallet, _amount, 0, 0, \"\");\n emit LockedFundsSentToL1(l1Wallet, msg.sender, address(manager), _amount);\n }\n}\n" + }, + "contracts/L2GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\n\n/**\n * @title L2GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * This L2 variant includes a special initializer so that it can be created from\n * a wallet's data received from L1. These transferred wallets will not allow releasing\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\n *\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\n // Initializer when created from a message from L1\n function initializeFromL1(\n address _manager,\n address _token,\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\n ) external {\n require(!isInitialized, \"Already initialized\");\n isInitialized = true;\n\n OwnableInitializable._initialize(_walletData.owner);\n beneficiary = _walletData.beneficiary;\n token = IERC20(_token);\n\n managedAmount = _walletData.managedAmount;\n\n startTime = _walletData.startTime;\n endTime = _walletData.endTime;\n periods = 1;\n isAccepted = true;\n\n // Optionals\n releaseStartTime = _walletData.endTime;\n revocable = Revocability.Disabled;\n\n _setManager(_manager);\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { Create2 } from \"@openzeppelin/contracts/utils/Create2.sol\";\n\n/**\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n * Based on https://eips.ethereum.org/EIPS/eip-1167\n */\ncontract MinimalProxyFactory {\n /// @dev Emitted when a new proxy is created\n event ProxyCreated(address indexed proxy);\n\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @dev Uses address(this) as deployer to compute the address. Only for backwards compatibility.\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation\n ) public view returns (address) {\n return getDeploymentAddress(_salt, _implementation, address(this));\n }\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _deployer Address of the deployer that creates the contract\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation,\n address _deployer\n ) public pure returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\n }\n\n /**\n * @dev Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @dev Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n /// @dev Owner of the contract, can be retrieved with the public owner() function\n address private _owner;\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\n /// to allow adding variables here without breaking the proxy storage layout\n uint256[50] private __gap;\n\n /// @dev Emitted when ownership of the contract is transferred\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function _initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/tests/arbitrum/AddressAliasHelper.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/84e64dee6ee82adbf8ec34fd4b86c207a61d9007/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n l2Address = address(uint160(l1Address) + offset);\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n l1Address = address(uint160(l2Address) - offset);\n }\n}\n" + }, + "contracts/tests/arbitrum/IBridge.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IBridge {\n event MessageDelivered(\n uint256 indexed messageIndex,\n bytes32 indexed beforeInboxAcc,\n address inbox,\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n );\n\n event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);\n\n event InboxToggle(address indexed inbox, bool enabled);\n\n event OutboxToggle(address indexed outbox, bool enabled);\n\n function deliverMessageToInbox(\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n ) external payable returns (uint256);\n\n function executeCall(\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (bool success, bytes memory returnData);\n\n // These are only callable by the admin\n function setInbox(address inbox, bool enabled) external;\n\n function setOutbox(address inbox, bool enabled) external;\n\n // View functions\n\n function activeOutbox() external view returns (address);\n\n function allowedInboxes(address inbox) external view returns (bool);\n\n function allowedOutboxes(address outbox) external view returns (bool);\n\n function inboxAccs(uint256 index) external view returns (bytes32);\n\n function messageCount() external view returns (uint256);\n}\n" + }, + "contracts/tests/arbitrum/IInbox.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nimport \"./IBridge.sol\";\nimport \"./IMessageProvider.sol\";\n\ninterface IInbox is IMessageProvider {\n function sendL2Message(bytes calldata messageData) external returns (uint256);\n\n function sendUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendL1FundedUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function sendL1FundedContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function createRetryableTicket(\n address destAddr,\n uint256 arbTxCallValue,\n uint256 maxSubmissionCost,\n address submissionRefundAddress,\n address valueRefundAddress,\n uint256 maxGas,\n uint256 gasPriceBid,\n bytes calldata data\n ) external payable returns (uint256);\n\n function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);\n\n function bridge() external view returns (IBridge);\n\n function pauseCreateRetryables() external;\n\n function unpauseCreateRetryables() external;\n\n function startRewriteAddress() external;\n\n function stopRewriteAddress() external;\n}\n" + }, + "contracts/tests/arbitrum/IMessageProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IMessageProvider {\n event InboxMessageDelivered(uint256 indexed messageNum, bytes data);\n\n event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);\n}\n" + }, + "contracts/tests/BridgeMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IBridge.sol\";\n\n/**\n * @title Arbitrum Bridge mock contract\n * @dev This contract implements Arbitrum's IBridge interface for testing purposes\n */\ncontract BridgeMock is IBridge {\n /// Address of the (mock) Arbitrum Inbox\n address public inbox;\n /// Address of the (mock) Arbitrum Outbox\n address public outbox;\n /// Index of the next message on the inbox messages array\n uint256 public messageIndex;\n /// Inbox messages array\n bytes32[] public override inboxAccs;\n\n /**\n * @notice Deliver a message to the inbox. The encoded message will be\n * added to the inbox array, and messageIndex will be incremented.\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the message data\n * @return The next index for the inbox array\n */\n function deliverMessageToInbox(\n uint8 _kind,\n address _sender,\n bytes32 _messageDataHash\n ) external payable override returns (uint256) {\n messageIndex = messageIndex + 1;\n inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash)));\n emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash);\n return messageIndex;\n }\n\n /**\n * @notice Executes an L1 function call incoing from L2. This can only be called\n * by the Outbox.\n * @param _destAddr Contract to call\n * @param _amount ETH value to send\n * @param _data Calldata for the function call\n * @return True if the call was successful, false otherwise\n * @return Return data from the call\n */\n function executeCall(\n address _destAddr,\n uint256 _amount,\n bytes calldata _data\n ) external override returns (bool, bytes memory) {\n require(outbox == msg.sender, \"NOT_FROM_OUTBOX\");\n bool success;\n bytes memory returnData;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, returnData) = _destAddr.call{ value: _amount }(_data);\n emit BridgeCallTriggered(msg.sender, _destAddr, _amount, _data);\n return (success, returnData);\n }\n\n /**\n * @notice Set the address of the inbox. Anyone can call this, because it's a mock.\n * @param _inbox Address of the inbox\n * @param _enabled Enable the inbox (ignored)\n */\n function setInbox(address _inbox, bool _enabled) external override {\n inbox = _inbox;\n emit InboxToggle(inbox, _enabled);\n }\n\n /**\n * @notice Set the address of the outbox. Anyone can call this, because it's a mock.\n * @param _outbox Address of the outbox\n * @param _enabled Enable the outbox (ignored)\n */\n function setOutbox(address _outbox, bool _enabled) external override {\n outbox = _outbox;\n emit OutboxToggle(outbox, _enabled);\n }\n\n // View functions\n\n /**\n * @notice Getter for the active outbox (in this case there's only one)\n */\n function activeOutbox() external view override returns (address) {\n return outbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed inbox (in this case there's only one)\n * @param _inbox Address to check\n * @return True if the address is the allowed inbox, false otherwise\n */\n function allowedInboxes(address _inbox) external view override returns (bool) {\n return _inbox == inbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed outbox (in this case there's only one)\n * @param _outbox Address to check\n * @return True if the address is the allowed outbox, false otherwise\n */\n function allowedOutboxes(address _outbox) external view override returns (bool) {\n return _outbox == outbox;\n }\n\n /**\n * @notice Getter for the count of messages in the inboxAccs\n * @return Number of messages in inboxAccs\n */\n function messageCount() external view override returns (uint256) {\n return inboxAccs.length;\n }\n}\n" + }, + "contracts/tests/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock contract.\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @notice Contract Constructor.\n * @param _initialSupply Initial supply\n * @param _mintTo Address to whitch to mint the initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n\n /**\n * @notice Mint tokens to an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _to Address to mint tokens to\n * @param _amount Amount of tokens to mint\n */\n function bridgeMint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n\n /**\n * @notice Burn tokens from an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _from Address to burn tokens from\n * @param _amount Amount of tokens to burn\n */\n function bridgeBurn(address _from, uint256 _amount) external {\n _burn(_from, _amount);\n }\n}\n" + }, + "contracts/tests/InboxMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IInbox.sol\";\nimport \"./arbitrum/AddressAliasHelper.sol\";\n\n/**\n * @title Arbitrum Inbox mock contract\n * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes\n */\ncontract InboxMock is IInbox {\n /// @dev Type indicator for a standard L2 message\n uint8 internal constant L2_MSG = 3;\n /// @dev Type indicator for a retryable ticket message\n // solhint-disable-next-line const-name-snakecase\n uint8 internal constant L1MessageType_submitRetryableTx = 9;\n /// Address of the Bridge (mock) contract\n IBridge public override bridge;\n\n /**\n * @notice Send a message to L2 (by delivering it to the Bridge)\n * @param _messageData Encoded data to send in the message\n * @return Message number returned by the inbox\n */\n function sendL2Message(bytes calldata _messageData) external override returns (uint256) {\n uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @notice Set the address of the (mock) bridge\n * @param _bridge Address of the bridge\n */\n function setBridge(address _bridge) external {\n bridge = IBridge(_bridge);\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendContractTransaction(\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedContractTransaction(\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Creates a retryable ticket for an L2 transaction\n * @param _destAddr Address of the contract to call in L2\n * @param _arbTxCallValue Callvalue to use in the L2 transaction\n * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei\n * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost\n * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled\n * @param _maxGas Max gas for the L2 transcation\n * @param _gasPriceBid Gas price bid on L2\n * @param _data Encoded calldata for the L2 transaction (including function selector)\n * @return Message number returned by the bridge\n */\n function createRetryableTicket(\n address _destAddr,\n uint256 _arbTxCallValue,\n uint256 _maxSubmissionCost,\n address _submissionRefundAddress,\n address _valueRefundAddress,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable override returns (uint256) {\n _submissionRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_submissionRefundAddress);\n _valueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_valueRefundAddress);\n return\n _deliverMessage(\n L1MessageType_submitRetryableTx,\n msg.sender,\n abi.encodePacked(\n uint256(uint160(bytes20(_destAddr))),\n _arbTxCallValue,\n msg.value,\n _maxSubmissionCost,\n uint256(uint160(bytes20(_submissionRefundAddress))),\n uint256(uint160(bytes20(_valueRefundAddress))),\n _maxGas,\n _gasPriceBid,\n _data.length,\n _data\n )\n );\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function depositEth(uint256) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function pauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function unpauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function startRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function stopRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageData Encoded message data\n * @return Message number returned by the bridge\n */\n function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) {\n uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the encoded message data\n * @return Message number returned by the bridge\n */\n function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) {\n return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash);\n }\n}\n" + }, + "contracts/tests/L1TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\n\n/**\n * @title L1 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L1TokenGatewayMock is Ownable {\n using SafeMath for uint256;\n /// Next sequence number to return when outboundTransfer is called\n uint256 public nextSeqNum;\n\n /// @dev Emitted when a (fake) retryable ticket is created\n event FakeTxToL2(\n address from,\n uint256 value,\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 maxSubmissionCost,\n bytes outboundCalldata\n );\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2\n event DepositInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L1 Token Gateway Contract Constructor.\n */\n constructor() {}\n\n /**\n * @notice Creates and sends a fake retryable ticket to transfer GRT to L2.\n * This mock will actually just emit an event with parameters equivalent to what the real L1GraphTokenGateway\n * would send to L2.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _maxGas Gas limit for L2 execution of the ticket\n * @param _gasPriceBid Price per gas on L2\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return Sequence number of the retryable ticket created by Inbox (always )\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 seqNum = nextSeqNum;\n nextSeqNum += 1;\n {\n uint256 maxSubmissionCost;\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, maxSubmissionCost, extraData) = _parseOutboundData(_data);\n require(maxSubmissionCost > 0, \"NO_SUBMISSION_COST\");\n\n {\n // makes sure only sufficient ETH is supplied as required for successful redemption on L2\n // if a user does not desire immediate redemption they should provide\n // a msg.value of AT LEAST maxSubmissionCost\n uint256 expectedEth = maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(msg.value >= expectedEth, \"WRONG_ETH_VALUE\");\n }\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // transfer tokens to escrow\n IERC20(_l1Token).transferFrom(from, address(this), _amount);\n\n emit FakeTxToL2(from, msg.value, _maxGas, _gasPriceBid, maxSubmissionCost, outboundCalldata);\n }\n }\n emit DepositInitiated(_l1Token, from, _to, seqNum, _amount);\n\n return abi.encode(seqNum);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L2\n * Actually does nothing, just keeping it here as its useful to define the expected\n * calldata for the outgoing transfer in tests.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recepient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {}\n\n /**\n * @notice Creates calldata required to create a retryable ticket\n * @dev encodes the target function with its params which\n * will be called on L2 when the retryable ticket is redeemed\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L1 from which we're transferring tokens\n * @param _to Address on L2 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L2 transaction, which must be empty unless the caller is whitelisted\n * @return Encoded calldata (including function selector) for the L2 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n bytes memory emptyBytes;\n\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(emptyBytes, _data)\n );\n }\n\n /**\n * @notice Decodes calldata required for transfer of tokens to L2\n * @dev Data must include maxSubmissionCost, extraData can be left empty. When the router\n * sends an outbound message, data also contains the from address, but this mock\n * doesn't consider this case\n * @param _data Encoded callhook data containing maxSubmissionCost and extraData\n * @return Sender of the tx\n * @return Max ether value used to submit the retryable ticket\n * @return Additional data sent to L2\n */\n function _parseOutboundData(bytes memory _data) private view returns (address, uint256, bytes memory) {\n address from;\n uint256 maxSubmissionCost;\n bytes memory extraData;\n from = msg.sender;\n // User-encoded data contains the max retryable ticket submission cost\n // and additional L2 calldata\n (maxSubmissionCost, extraData) = abi.decode(_data, (uint256, bytes));\n return (from, maxSubmissionCost, extraData);\n }\n}\n" + }, + "contracts/tests/L2TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\nimport { GraphTokenMock } from \"./GraphTokenMock.sol\";\nimport { ICallhookReceiver } from \"../ICallhookReceiver.sol\";\n\n/**\n * @title L2 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L2TokenGatewayMock is Ownable {\n /// Address of the L1 GRT contract\n address public immutable l1Token;\n /// Address of the L2 GRT contract\n address public immutable l2Token;\n /// Next ID to return when sending an outboundTransfer\n uint256 public nextId;\n\n /// @dev Emitted when a (fake) transaction to L1 is created\n event FakeTxToL1(address from, bytes outboundCalldata);\n /// @dev Emitted when a (fake) retryable ticket is received from L1\n event DepositFinalized(address token, address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are withdrawn to L1 from L2\n event WithdrawalInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L2 Token Gateway Contract Constructor.\n * @param _l1Token Address of the L1 GRT contract\n * @param _l2Token Address of the L2 GRT contract\n */\n constructor(address _l1Token, address _l2Token) {\n l1Token = _l1Token;\n l2Token = _l2Token;\n }\n\n /**\n * @notice Creates and sends a (fake) transfer of GRT to L1.\n * This mock will actually just emit an event with parameters equivalent to what the real L2GraphTokenGateway\n * would send to L1.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return ID of the L2-L1 message (incrementing on every call)\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_l1Token == l1Token, \"INVALID_L1_TOKEN\");\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 id = nextId;\n nextId += 1;\n {\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, extraData) = _parseOutboundData(_data);\n\n require(msg.value == 0, \"!value\");\n require(extraData.length == 0, \"!extraData\");\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // burn tokens from the sender, they will be released from escrow in L1\n GraphTokenMock(l2Token).bridgeBurn(from, _amount);\n\n emit FakeTxToL1(from, outboundCalldata);\n }\n }\n emit WithdrawalInitiated(_l1Token, from, _to, id, _amount);\n\n return abi.encode(id);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L1\n * Implements calling callhooks if data is non-empty.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recipient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata, will trigger an onTokenTransfer call if non-empty\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {\n require(_l1Token == l1Token, \"TOKEN_NOT_GRT\");\n require(msg.value == 0, \"INVALID_NONZERO_VALUE\");\n\n GraphTokenMock(l2Token).bridgeMint(_to, _amount);\n\n if (_data.length > 0) {\n ICallhookReceiver(_to).onTokenTransfer(_from, _amount, _data);\n }\n\n emit DepositFinalized(_l1Token, _from, _to, _amount);\n }\n\n /**\n * @notice Calculate the L2 address of a bridged token\n * @dev In our case, this would only work for GRT.\n * @param l1ERC20 address of L1 GRT contract\n * @return L2 address of the bridged GRT token\n */\n function calculateL2TokenAddress(address l1ERC20) public view returns (address) {\n if (l1ERC20 != l1Token) {\n return address(0);\n }\n return l2Token;\n }\n\n /**\n * @notice Creates calldata required to create a tx to L1\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L2 from which we're transferring tokens\n * @param _to Address on L1 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L1 transaction, which must be empty\n * @return Encoded calldata (including function selector) for the L1 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(0, _data)\n );\n }\n\n /**\n * @dev Decodes calldata required for transfer of tokens to L1.\n * extraData can be left empty\n * @param _data Encoded callhook data\n * @return Sender of the tx\n * @return Any other data sent to L1\n */\n function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {\n address from;\n bytes memory extraData;\n // The mock doesn't take messages from the Router\n from = msg.sender;\n extraData = _data;\n return (from, extraData);\n }\n}\n" + }, + "contracts/tests/Stakes.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(\n Stakes.Indexer memory stake,\n uint256 _delegatedCapacity\n ) internal pure returns (uint256) {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "contracts/tests/StakingMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n receive() external payable {}\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/tests/WalletMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title WalletMock: a mock wallet contract for testing purposes\n * @dev For testing only, DO NOT USE IN PRODUCTION.\n * This is used to test L1-L2 transfer tools and to create scenarios\n * where an invalid wallet calls the transfer tool, e.g. a wallet that has an invalid\n * manager, or a wallet that has not been initialized.\n */\ncontract WalletMock {\n /// Target contract for the fallback function (usually a transfer tool contract)\n address public immutable target;\n /// Address of the GRT (mock) token\n address public immutable token;\n /// Address of the wallet's manager\n address public immutable manager;\n /// Whether the wallet has been initialized\n bool public immutable isInitialized;\n /// Whether the beneficiary has accepted the lock\n bool public immutable isAccepted;\n\n /**\n * @notice WalletMock constructor\n * @dev This constructor sets all the state variables so that\n * specific test scenarios can be created just by deploying this contract.\n * @param _target Target contract for the fallback function\n * @param _token Address of the GRT (mock) token\n * @param _manager Address of the wallet's manager\n * @param _isInitialized Whether the wallet has been initialized\n * @param _isAccepted Whether the beneficiary has accepted the lock\n */\n constructor(address _target, address _token, address _manager, bool _isInitialized, bool _isAccepted) {\n target = _target;\n token = _token;\n manager = _manager;\n isInitialized = _isInitialized;\n isAccepted = _isAccepted;\n }\n\n /**\n * @notice Fallback function\n * @dev This function calls the target contract with the data sent to this contract.\n * This is used to test the L1-L2 transfer tool.\n */\n fallback() external payable {\n // Call function with data\n Address.functionCall(target, msg.data);\n }\n\n /**\n * @notice Receive function\n * @dev This function is added to avoid compiler warnings, but just reverts.\n */\n receive() external payable {\n revert(\"Invalid call\");\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/.chainId b/packages/token-distribution/deployments/goerli/.chainId new file mode 100644 index 000000000..7813681f5 --- /dev/null +++ b/packages/token-distribution/deployments/goerli/.chainId @@ -0,0 +1 @@ +5 \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/GraphTokenLockManager-Testnet.json b/packages/token-distribution/deployments/goerli/GraphTokenLockManager-Testnet.json new file mode 100644 index 000000000..ec1a15ebd --- /dev/null +++ b/packages/token-distribution/deployments/goerli/GraphTokenLockManager-Testnet.json @@ -0,0 +1,932 @@ +{ + "address": "0xF3b617e0c966329363e78c266361794e84223313", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x8ff337497a43f11d369102c1f1fcdca0475f0e8d199f0ce61f1012cdba528455", + "receipt": { + "to": null, + "from": "0xB15599AC1261C4828Ac7E66383ae520655d3D300", + "contractAddress": "0xF3b617e0c966329363e78c266361794e84223313", + "transactionIndex": 33, + "gasUsed": "3166750", + "logsBloom": "0x00000000000000000000000000020000000004010000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000400000000000040000020000000000000000000800000000000000000001000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000010000000000002000000002000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000000100000000000000000", + "blockHash": "0x3d4f81bf12b0231ab0b12d7c4f6f27334416efae9396ec4ec8f2766e1a0bc75e", + "transactionHash": "0x8ff337497a43f11d369102c1f1fcdca0475f0e8d199f0ce61f1012cdba528455", + "logs": [ + { + "transactionIndex": 33, + "blockNumber": 9345443, + "transactionHash": "0x8ff337497a43f11d369102c1f1fcdca0475f0e8d199f0ce61f1012cdba528455", + "address": "0xF3b617e0c966329363e78c266361794e84223313", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000b15599ac1261c4828ac7e66383ae520655d3d300" + ], + "data": "0x", + "logIndex": 2063, + "blockHash": "0x3d4f81bf12b0231ab0b12d7c4f6f27334416efae9396ec4ec8f2766e1a0bc75e" + }, + { + "transactionIndex": 33, + "blockNumber": 9345443, + "transactionHash": "0x8ff337497a43f11d369102c1f1fcdca0475f0e8d199f0ce61f1012cdba528455", + "address": "0xF3b617e0c966329363e78c266361794e84223313", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x000000000000000000000000c93df24c3a1ebeccd0e5d41198460081cfb38c49" + ], + "data": "0x", + "logIndex": 2064, + "blockHash": "0x3d4f81bf12b0231ab0b12d7c4f6f27334416efae9396ec4ec8f2766e1a0bc75e" + } + ], + "blockNumber": 9345443, + "cumulativeGasUsed": "11138915", + "status": 1, + "byzantium": true + }, + "args": [ + "0x5c946740441C12510a167B447B7dE565C20b9E3C", + "0xc93df24c3A1ebeCcd0e5D41198460081CFB38c49" + ], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003c8f38038062003c8f83398181016040528101906200003791906200039c565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004e7565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b505062000596565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001f26200034560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200024b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024290620004c5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b590620004a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000815190506200037f8162000562565b92915050565b60008151905062000396816200057c565b92915050565b60008060408385031215620003b057600080fd5b6000620003c08582860162000385565b9250506020620003d3858286016200036e565b9150509250929050565b6000620003ec60198362000509565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006200042e60208362000509565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200047060148362000509565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004be81620003dd565b9050919050565b60006020820190508181036000830152620004e0816200041f565b9050919050565b60006020820190508181036000830152620005028162000461565b9050919050565b600082825260208201905092915050565b6000620005278262000542565b9050919050565b60006200053b826200051a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200056d816200051a565b81146200057957600080fd5b50565b62000587816200052e565b81146200059357600080fd5b50565b6136e980620005a66000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80638da5cb5b116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80638da5cb5b146102875780639c05fc60146102a5578063a3457466146102c1578063a619486e146102df578063b6b55f25146102fd5761012c565b80635975e00c116100f45780635975e00c146101e557806368d30c2e146102015780636e03b8dc1461021d578063715018a61461024d57806379ee1bdf146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d57806343fb93d914610199578063463013a2146101c9575b600080fd5b61014b6004803603810190610146919061253a565b6103bb565b005b61016760048036038101906101629190612511565b610563565b6040516101749190613029565b60405180910390f35b610197600480360381019061019291906125d7565b6105a4565b005b6101b360048036038101906101ae91906124c2565b610701565b6040516101c09190612e63565b60405180910390f35b6101e360048036038101906101de919061257f565b610726565b005b6101ff60048036038101906101fa9190612335565b6107b2565b005b61021b6004803603810190610216919061235e565b610943565b005b61023760048036038101906102329190612511565b610c8b565b6040516102449190612e63565b60405180910390f35b610255610cbe565b005b610271600480360381019061026c9190612335565b610df8565b60405161027e9190613029565b60405180910390f35b61028f610e15565b60405161029c9190612e63565b60405180910390f35b6102bf60048036038101906102ba9190612424565b610e3e565b005b6102c9610f6b565b6040516102d69190613007565b60405180910390f35b6102e7611043565b6040516102f49190612e63565b60405180910390f35b610317600480360381019061031291906125d7565b611069565b005b610333600480360381019061032e9190612335565b61114c565b005b61034f600480360381019061034a9190612335565b61126d565b005b61036b60048036038101906103669190612511565b6113e0565b6040516103789190612e63565b60405180910390f35b61039b60048036038101906103969190612335565b61145b565b005b6103a5611604565b6040516103b29190613044565b60405180910390f35b6103c361162e565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613225565b60405180910390fd5b60006104438383611636565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9868660405161055692919061305f565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113e0565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac61162e565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613225565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613205565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613305565b60405180910390a250565b600061071d846107108561174a565b80519060200120846117c0565b90509392505050565b61072e61162e565b73ffffffffffffffffffffffffffffffffffffffff1661074c610e15565b73ffffffffffffffffffffffffffffffffffffffff16146107a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079990613225565b60405180910390fd5b6107ad838383611804565b505050565b6107ba61162e565b73ffffffffffffffffffffffffffffffffffffffff166107d8610e15565b73ffffffffffffffffffffffffffffffffffffffff161461082e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082590613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561089e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089590613105565b60405180910390fd5b6108b28160026119e690919063ffffffff16565b6108f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e890613265565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960016040516109389190613029565b60405180910390a250565b61094b61162e565b73ffffffffffffffffffffffffffffffffffffffff16610969610e15565b73ffffffffffffffffffffffffffffffffffffffff16146109bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b690613225565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a1b9190612e63565b60206040518083038186803b158015610a3357600080fd5b505afa158015610a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6b9190612600565b1015610aac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa390613145565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610afd9b9a99989796959493929190612e7e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b928280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a16565b9050610be1818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c76989796959493929190612f89565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cc661162e565b73ffffffffffffffffffffffffffffffffffffffff16610ce4610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610d3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3190613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e0e826002611a9290919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e4661162e565b73ffffffffffffffffffffffffffffffffffffffff16610e64610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610eba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb190613225565b60405180910390fd5b818190508484905014610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef9906130e5565b60405180910390fd5b60005b84849050811015610f6457610f57858583818110610f1f57fe5b9050602002810190610f319190613320565b858585818110610f3d57fe5b9050602002016020810190610f529190612335565b611804565b8080600101915050610f05565b5050505050565b606080610f786002611ac2565b67ffffffffffffffff81118015610f8e57600080fd5b50604051908082528060200260200182016040528015610fbd5781602001602082028036833780820191505090505b50905060005b610fcd6002611ac2565b81101561103b57610fe8816002611ad790919063ffffffff16565b828281518110610ff457fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fc3565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116110ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a390613205565b60405180910390fd5b6110fb333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611af1909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111419190613305565b60405180910390a250565b61115461162e565b73ffffffffffffffffffffffffffffffffffffffff16611172610e15565b73ffffffffffffffffffffffffffffffffffffffff16146111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf90613225565b60405180910390fd5b6111dc816002611b7a90919063ffffffff16565b61121b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121290613185565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516112629190613029565b60405180910390a250565b61127561162e565b73ffffffffffffffffffffffffffffffffffffffff16611293610e15565b73ffffffffffffffffffffffffffffffffffffffff16146112e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112e090613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611359576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611350906131a5565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61146361162e565b73ffffffffffffffffffffffffffffffffffffffff16611481610e15565b73ffffffffffffffffffffffffffffffffffffffff16146114d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ce90613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153e90613125565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116bc83836040516024016040516020818303038152906040529190604051611662929190612e4a565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611baa565b905092915050565b6117458363a9059cbb60e01b84846040516024016116e3929190612f60565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b9050838383836040516020016117a69493929190612d97565b604051602081830303815290604052945050505050919050565b60008060ff60f81b8386866040516020016117de9493929190612de5565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161186a906131c5565b60405180910390fd5b61187c81611cc9565b6118bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b2906132e5565b60405180910390fd5b60006118c78484611636565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516119d892919061305f565b60405180910390a450505050565b6000611a0e836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cdc565b905092915050565b600080611a2d600086611a288761174a565b611d4c565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611a8757611a858184611e5d565b505b809150509392505050565b6000611aba836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ea7565b905092915050565b6000611ad082600001611eca565b9050919050565b6000611ae68360000183611edb565b60001c905092915050565b611b74846323b872dd60e01b858585604051602401611b1293929190612f29565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b50505050565b6000611ba2836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f48565b905092915050565b60006004825114611bf0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be790613245565b60405180910390fd5b60006020830151905080915050919050565b6060611c64826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120309092919063ffffffff16565b9050600081511115611cc45780806020019051810190611c849190612499565b611cc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cba906132a5565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611ce88383611ea7565b611d41578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d46565b600090505b92915050565b60008084471015611d92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d89906132c5565b60405180910390fd5b600083511415611dd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dce906130c5565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e49906131e5565b60405180910390fd5b809150509392505050565b6060611e9f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612030565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1d906130a5565b60405180910390fd5b826000018281548110611f3557fe5b9060005260206000200154905092915050565b600080836001016000848152602001908152602001600020549050600081146120245760006001820390506000600186600001805490500390506000866000018281548110611f9357fe5b9060005260206000200154905080876000018481548110611fb057fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fe857fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061202a565b60009150505b92915050565b606061203f8484600085612048565b90509392505050565b60608247101561208d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208490613165565b60405180910390fd5b61209685611cc9565b6120d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120cc90613285565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516120ff9190612e33565b60006040518083038185875af1925050503d806000811461213c576040519150601f19603f3d011682016040523d82523d6000602084013e612141565b606091505b509150915061215182828661215d565b92505050949350505050565b6060831561216d578290506121bd565b6000835111156121805782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121b49190613083565b60405180910390fd5b9392505050565b6000813590506121d381613630565b92915050565b60008083601f8401126121eb57600080fd5b8235905067ffffffffffffffff81111561220457600080fd5b60208301915083602082028301111561221c57600080fd5b9250929050565b60008083601f84011261223557600080fd5b8235905067ffffffffffffffff81111561224e57600080fd5b60208301915083602082028301111561226657600080fd5b9250929050565b60008151905061227c81613647565b92915050565b6000813590506122918161365e565b92915050565b6000813590506122a681613675565b92915050565b6000813590506122bb8161368c565b92915050565b60008083601f8401126122d357600080fd5b8235905067ffffffffffffffff8111156122ec57600080fd5b60208301915083600182028301111561230457600080fd5b9250929050565b60008135905061231a8161369c565b92915050565b60008151905061232f8161369c565b92915050565b60006020828403121561234757600080fd5b6000612355848285016121c4565b91505092915050565b60008060008060008060008060006101208a8c03121561237d57600080fd5b600061238b8c828d016121c4565b995050602061239c8c828d016121c4565b98505060406123ad8c828d0161230b565b97505060606123be8c828d0161230b565b96505060806123cf8c828d0161230b565b95505060a06123e08c828d0161230b565b94505060c06123f18c828d0161230b565b93505060e06124028c828d0161230b565b9250506101006124148c828d016122ac565b9150509295985092959850929598565b6000806000806040858703121561243a57600080fd5b600085013567ffffffffffffffff81111561245457600080fd5b61246087828801612223565b9450945050602085013567ffffffffffffffff81111561247f57600080fd5b61248b878288016121d9565b925092505092959194509250565b6000602082840312156124ab57600080fd5b60006124b98482850161226d565b91505092915050565b6000806000606084860312156124d757600080fd5b60006124e586828701612282565b93505060206124f6868287016121c4565b9250506040612507868287016121c4565b9150509250925092565b60006020828403121561252357600080fd5b600061253184828501612297565b91505092915050565b6000806020838503121561254d57600080fd5b600083013567ffffffffffffffff81111561256757600080fd5b612573858286016122c1565b92509250509250929050565b60008060006040848603121561259457600080fd5b600084013567ffffffffffffffff8111156125ae57600080fd5b6125ba868287016122c1565b935093505060206125cd868287016121c4565b9150509250925092565b6000602082840312156125e957600080fd5b60006125f78482850161230b565b91505092915050565b60006020828403121561261257600080fd5b600061262084828501612320565b91505092915050565b60006126358383612641565b60208301905092915050565b61264a816133ed565b82525050565b612659816133ed565b82525050565b61267061266b826133ed565b6135a6565b82525050565b600061268182613387565b61268b81856133b5565b935061269683613377565b8060005b838110156126c75781516126ae8882612629565b97506126b9836133a8565b92505060018101905061269a565b5085935050505092915050565b6126dd816133ff565b82525050565b6126f46126ef82613437565b6135c2565b82525050565b61270b61270682613463565b6135cc565b82525050565b61272261271d8261340b565b6135b8565b82525050565b6127396127348261348f565b6135d6565b82525050565b61275061274b826134bb565b6135e0565b82525050565b600061276182613392565b61276b81856133c6565b935061277b818560208601613573565b80840191505092915050565b6127908161352e565b82525050565b61279f81613552565b82525050565b60006127b183856133d1565b93506127be838584613564565b6127c7836135fe565b840190509392505050565b60006127de83856133e2565b93506127eb838584613564565b82840190509392505050565b60006128028261339d565b61280c81856133d1565b935061281c818560208601613573565b612825816135fe565b840191505092915050565b600061283d6022836133d1565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a36020836133d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e36015836133d1565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612923601a836133d1565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129636026836133d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129c96020836133d1565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a096026836133d1565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a6f601b836133d1565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612aaf6019836133d1565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612aef601d836133d1565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b2f6019836133d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b6f6015836133d1565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612baf6020836133d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bef6018836133d1565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c2f6019836133d1565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c6f601d836133d1565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612caf602a836133d1565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d15601d836133d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d556019836133d1565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9181613524565b82525050565b6000612da382876126e3565b600a82019150612db382866126e3565b600a82019150612dc38285612728565b601482019150612dd382846126fa565b600f8201915081905095945050505050565b6000612df18287612711565b600182019150612e01828661265f565b601482019150612e11828561273f565b602082019150612e21828461273f565b60208201915081905095945050505050565b6000612e3f8284612756565b915081905092915050565b6000612e578284866127d2565b91508190509392505050565b6000602082019050612e786000830184612650565b92915050565b600061016082019050612e94600083018e612650565b612ea1602083018d612650565b612eae604083018c612650565b612ebb606083018b612650565b612ec8608083018a612d88565b612ed560a0830189612d88565b612ee260c0830188612d88565b612eef60e0830187612d88565b612efd610100830186612d88565b612f0b610120830185612d88565b612f19610140830184612796565b9c9b505050505050505050505050565b6000606082019050612f3e6000830186612650565b612f4b6020830185612650565b612f586040830184612d88565b949350505050565b6000604082019050612f756000830185612650565b612f826020830184612d88565b9392505050565b600061010082019050612f9f600083018b612650565b612fac602083018a612d88565b612fb96040830189612d88565b612fc66060830188612d88565b612fd36080830187612d88565b612fe060a0830186612d88565b612fed60c0830185612d88565b612ffa60e0830184612796565b9998505050505050505050565b600060208201905081810360008301526130218184612676565b905092915050565b600060208201905061303e60008301846126d4565b92915050565b60006020820190506130596000830184612787565b92915050565b6000602082019050818103600083015261307a8184866127a5565b90509392505050565b6000602082019050818103600083015261309d81846127f7565b905092915050565b600060208201905081810360008301526130be81612830565b9050919050565b600060208201905081810360008301526130de81612896565b9050919050565b600060208201905081810360008301526130fe816128d6565b9050919050565b6000602082019050818103600083015261311e81612916565b9050919050565b6000602082019050818103600083015261313e81612956565b9050919050565b6000602082019050818103600083015261315e816129bc565b9050919050565b6000602082019050818103600083015261317e816129fc565b9050919050565b6000602082019050818103600083015261319e81612a62565b9050919050565b600060208201905081810360008301526131be81612aa2565b9050919050565b600060208201905081810360008301526131de81612ae2565b9050919050565b600060208201905081810360008301526131fe81612b22565b9050919050565b6000602082019050818103600083015261321e81612b62565b9050919050565b6000602082019050818103600083015261323e81612ba2565b9050919050565b6000602082019050818103600083015261325e81612be2565b9050919050565b6000602082019050818103600083015261327e81612c22565b9050919050565b6000602082019050818103600083015261329e81612c62565b9050919050565b600060208201905081810360008301526132be81612ca2565b9050919050565b600060208201905081810360008301526132de81612d08565b9050919050565b600060208201905081810360008301526132fe81612d48565b9050919050565b600060208201905061331a6000830184612d88565b92915050565b6000808335600160200384360303811261333957600080fd5b80840192508235915067ffffffffffffffff82111561335757600080fd5b60208301925060018202360383131561336f57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133f882613504565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506134ff8261361c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353982613540565b9050919050565b600061354b82613504565b9050919050565b600061355d826134f1565b9050919050565b82818337600083830152505050565b60005b83811015613591578082015181840152602081019050613576565b838111156135a0576000848401525b50505050565b60006135b1826135ea565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f58261360f565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061362d5761362c6135fc565b5b50565b613639816133ed565b811461364457600080fd5b50565b613650816133ff565b811461365b57600080fd5b50565b613667816134bb565b811461367257600080fd5b50565b61367e816134c5565b811461368957600080fd5b50565b6003811061369957600080fd5b50565b6136a581613524565b81146136b057600080fd5b5056fea2646970667358221220d5c9f5b6d4e12c49170d8830f9459ebc2386434f550d65bae2bbc0fcfbacfb6264736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80638da5cb5b116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80638da5cb5b146102875780639c05fc60146102a5578063a3457466146102c1578063a619486e146102df578063b6b55f25146102fd5761012c565b80635975e00c116100f45780635975e00c146101e557806368d30c2e146102015780636e03b8dc1461021d578063715018a61461024d57806379ee1bdf146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d57806343fb93d914610199578063463013a2146101c9575b600080fd5b61014b6004803603810190610146919061253a565b6103bb565b005b61016760048036038101906101629190612511565b610563565b6040516101749190613029565b60405180910390f35b610197600480360381019061019291906125d7565b6105a4565b005b6101b360048036038101906101ae91906124c2565b610701565b6040516101c09190612e63565b60405180910390f35b6101e360048036038101906101de919061257f565b610726565b005b6101ff60048036038101906101fa9190612335565b6107b2565b005b61021b6004803603810190610216919061235e565b610943565b005b61023760048036038101906102329190612511565b610c8b565b6040516102449190612e63565b60405180910390f35b610255610cbe565b005b610271600480360381019061026c9190612335565b610df8565b60405161027e9190613029565b60405180910390f35b61028f610e15565b60405161029c9190612e63565b60405180910390f35b6102bf60048036038101906102ba9190612424565b610e3e565b005b6102c9610f6b565b6040516102d69190613007565b60405180910390f35b6102e7611043565b6040516102f49190612e63565b60405180910390f35b610317600480360381019061031291906125d7565b611069565b005b610333600480360381019061032e9190612335565b61114c565b005b61034f600480360381019061034a9190612335565b61126d565b005b61036b60048036038101906103669190612511565b6113e0565b6040516103789190612e63565b60405180910390f35b61039b60048036038101906103969190612335565b61145b565b005b6103a5611604565b6040516103b29190613044565b60405180910390f35b6103c361162e565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613225565b60405180910390fd5b60006104438383611636565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9868660405161055692919061305f565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113e0565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac61162e565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613225565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613205565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613305565b60405180910390a250565b600061071d846107108561174a565b80519060200120846117c0565b90509392505050565b61072e61162e565b73ffffffffffffffffffffffffffffffffffffffff1661074c610e15565b73ffffffffffffffffffffffffffffffffffffffff16146107a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079990613225565b60405180910390fd5b6107ad838383611804565b505050565b6107ba61162e565b73ffffffffffffffffffffffffffffffffffffffff166107d8610e15565b73ffffffffffffffffffffffffffffffffffffffff161461082e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082590613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561089e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089590613105565b60405180910390fd5b6108b28160026119e690919063ffffffff16565b6108f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e890613265565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960016040516109389190613029565b60405180910390a250565b61094b61162e565b73ffffffffffffffffffffffffffffffffffffffff16610969610e15565b73ffffffffffffffffffffffffffffffffffffffff16146109bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b690613225565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a1b9190612e63565b60206040518083038186803b158015610a3357600080fd5b505afa158015610a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6b9190612600565b1015610aac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa390613145565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610afd9b9a99989796959493929190612e7e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b928280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a16565b9050610be1818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c76989796959493929190612f89565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cc661162e565b73ffffffffffffffffffffffffffffffffffffffff16610ce4610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610d3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3190613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e0e826002611a9290919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e4661162e565b73ffffffffffffffffffffffffffffffffffffffff16610e64610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610eba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb190613225565b60405180910390fd5b818190508484905014610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef9906130e5565b60405180910390fd5b60005b84849050811015610f6457610f57858583818110610f1f57fe5b9050602002810190610f319190613320565b858585818110610f3d57fe5b9050602002016020810190610f529190612335565b611804565b8080600101915050610f05565b5050505050565b606080610f786002611ac2565b67ffffffffffffffff81118015610f8e57600080fd5b50604051908082528060200260200182016040528015610fbd5781602001602082028036833780820191505090505b50905060005b610fcd6002611ac2565b81101561103b57610fe8816002611ad790919063ffffffff16565b828281518110610ff457fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fc3565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116110ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a390613205565b60405180910390fd5b6110fb333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611af1909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111419190613305565b60405180910390a250565b61115461162e565b73ffffffffffffffffffffffffffffffffffffffff16611172610e15565b73ffffffffffffffffffffffffffffffffffffffff16146111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf90613225565b60405180910390fd5b6111dc816002611b7a90919063ffffffff16565b61121b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121290613185565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516112629190613029565b60405180910390a250565b61127561162e565b73ffffffffffffffffffffffffffffffffffffffff16611293610e15565b73ffffffffffffffffffffffffffffffffffffffff16146112e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112e090613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611359576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611350906131a5565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61146361162e565b73ffffffffffffffffffffffffffffffffffffffff16611481610e15565b73ffffffffffffffffffffffffffffffffffffffff16146114d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ce90613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153e90613125565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116bc83836040516024016040516020818303038152906040529190604051611662929190612e4a565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611baa565b905092915050565b6117458363a9059cbb60e01b84846040516024016116e3929190612f60565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b9050838383836040516020016117a69493929190612d97565b604051602081830303815290604052945050505050919050565b60008060ff60f81b8386866040516020016117de9493929190612de5565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161186a906131c5565b60405180910390fd5b61187c81611cc9565b6118bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b2906132e5565b60405180910390fd5b60006118c78484611636565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516119d892919061305f565b60405180910390a450505050565b6000611a0e836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cdc565b905092915050565b600080611a2d600086611a288761174a565b611d4c565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611a8757611a858184611e5d565b505b809150509392505050565b6000611aba836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ea7565b905092915050565b6000611ad082600001611eca565b9050919050565b6000611ae68360000183611edb565b60001c905092915050565b611b74846323b872dd60e01b858585604051602401611b1293929190612f29565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b50505050565b6000611ba2836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f48565b905092915050565b60006004825114611bf0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be790613245565b60405180910390fd5b60006020830151905080915050919050565b6060611c64826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120309092919063ffffffff16565b9050600081511115611cc45780806020019051810190611c849190612499565b611cc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cba906132a5565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611ce88383611ea7565b611d41578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d46565b600090505b92915050565b60008084471015611d92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d89906132c5565b60405180910390fd5b600083511415611dd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dce906130c5565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e49906131e5565b60405180910390fd5b809150509392505050565b6060611e9f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612030565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1d906130a5565b60405180910390fd5b826000018281548110611f3557fe5b9060005260206000200154905092915050565b600080836001016000848152602001908152602001600020549050600081146120245760006001820390506000600186600001805490500390506000866000018281548110611f9357fe5b9060005260206000200154905080876000018481548110611fb057fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fe857fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061202a565b60009150505b92915050565b606061203f8484600085612048565b90509392505050565b60608247101561208d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208490613165565b60405180910390fd5b61209685611cc9565b6120d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120cc90613285565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516120ff9190612e33565b60006040518083038185875af1925050503d806000811461213c576040519150601f19603f3d011682016040523d82523d6000602084013e612141565b606091505b509150915061215182828661215d565b92505050949350505050565b6060831561216d578290506121bd565b6000835111156121805782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121b49190613083565b60405180910390fd5b9392505050565b6000813590506121d381613630565b92915050565b60008083601f8401126121eb57600080fd5b8235905067ffffffffffffffff81111561220457600080fd5b60208301915083602082028301111561221c57600080fd5b9250929050565b60008083601f84011261223557600080fd5b8235905067ffffffffffffffff81111561224e57600080fd5b60208301915083602082028301111561226657600080fd5b9250929050565b60008151905061227c81613647565b92915050565b6000813590506122918161365e565b92915050565b6000813590506122a681613675565b92915050565b6000813590506122bb8161368c565b92915050565b60008083601f8401126122d357600080fd5b8235905067ffffffffffffffff8111156122ec57600080fd5b60208301915083600182028301111561230457600080fd5b9250929050565b60008135905061231a8161369c565b92915050565b60008151905061232f8161369c565b92915050565b60006020828403121561234757600080fd5b6000612355848285016121c4565b91505092915050565b60008060008060008060008060006101208a8c03121561237d57600080fd5b600061238b8c828d016121c4565b995050602061239c8c828d016121c4565b98505060406123ad8c828d0161230b565b97505060606123be8c828d0161230b565b96505060806123cf8c828d0161230b565b95505060a06123e08c828d0161230b565b94505060c06123f18c828d0161230b565b93505060e06124028c828d0161230b565b9250506101006124148c828d016122ac565b9150509295985092959850929598565b6000806000806040858703121561243a57600080fd5b600085013567ffffffffffffffff81111561245457600080fd5b61246087828801612223565b9450945050602085013567ffffffffffffffff81111561247f57600080fd5b61248b878288016121d9565b925092505092959194509250565b6000602082840312156124ab57600080fd5b60006124b98482850161226d565b91505092915050565b6000806000606084860312156124d757600080fd5b60006124e586828701612282565b93505060206124f6868287016121c4565b9250506040612507868287016121c4565b9150509250925092565b60006020828403121561252357600080fd5b600061253184828501612297565b91505092915050565b6000806020838503121561254d57600080fd5b600083013567ffffffffffffffff81111561256757600080fd5b612573858286016122c1565b92509250509250929050565b60008060006040848603121561259457600080fd5b600084013567ffffffffffffffff8111156125ae57600080fd5b6125ba868287016122c1565b935093505060206125cd868287016121c4565b9150509250925092565b6000602082840312156125e957600080fd5b60006125f78482850161230b565b91505092915050565b60006020828403121561261257600080fd5b600061262084828501612320565b91505092915050565b60006126358383612641565b60208301905092915050565b61264a816133ed565b82525050565b612659816133ed565b82525050565b61267061266b826133ed565b6135a6565b82525050565b600061268182613387565b61268b81856133b5565b935061269683613377565b8060005b838110156126c75781516126ae8882612629565b97506126b9836133a8565b92505060018101905061269a565b5085935050505092915050565b6126dd816133ff565b82525050565b6126f46126ef82613437565b6135c2565b82525050565b61270b61270682613463565b6135cc565b82525050565b61272261271d8261340b565b6135b8565b82525050565b6127396127348261348f565b6135d6565b82525050565b61275061274b826134bb565b6135e0565b82525050565b600061276182613392565b61276b81856133c6565b935061277b818560208601613573565b80840191505092915050565b6127908161352e565b82525050565b61279f81613552565b82525050565b60006127b183856133d1565b93506127be838584613564565b6127c7836135fe565b840190509392505050565b60006127de83856133e2565b93506127eb838584613564565b82840190509392505050565b60006128028261339d565b61280c81856133d1565b935061281c818560208601613573565b612825816135fe565b840191505092915050565b600061283d6022836133d1565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a36020836133d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e36015836133d1565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612923601a836133d1565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129636026836133d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129c96020836133d1565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a096026836133d1565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a6f601b836133d1565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612aaf6019836133d1565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612aef601d836133d1565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b2f6019836133d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b6f6015836133d1565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612baf6020836133d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bef6018836133d1565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c2f6019836133d1565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c6f601d836133d1565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612caf602a836133d1565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d15601d836133d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d556019836133d1565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9181613524565b82525050565b6000612da382876126e3565b600a82019150612db382866126e3565b600a82019150612dc38285612728565b601482019150612dd382846126fa565b600f8201915081905095945050505050565b6000612df18287612711565b600182019150612e01828661265f565b601482019150612e11828561273f565b602082019150612e21828461273f565b60208201915081905095945050505050565b6000612e3f8284612756565b915081905092915050565b6000612e578284866127d2565b91508190509392505050565b6000602082019050612e786000830184612650565b92915050565b600061016082019050612e94600083018e612650565b612ea1602083018d612650565b612eae604083018c612650565b612ebb606083018b612650565b612ec8608083018a612d88565b612ed560a0830189612d88565b612ee260c0830188612d88565b612eef60e0830187612d88565b612efd610100830186612d88565b612f0b610120830185612d88565b612f19610140830184612796565b9c9b505050505050505050505050565b6000606082019050612f3e6000830186612650565b612f4b6020830185612650565b612f586040830184612d88565b949350505050565b6000604082019050612f756000830185612650565b612f826020830184612d88565b9392505050565b600061010082019050612f9f600083018b612650565b612fac602083018a612d88565b612fb96040830189612d88565b612fc66060830188612d88565b612fd36080830187612d88565b612fe060a0830186612d88565b612fed60c0830185612d88565b612ffa60e0830184612796565b9998505050505050505050565b600060208201905081810360008301526130218184612676565b905092915050565b600060208201905061303e60008301846126d4565b92915050565b60006020820190506130596000830184612787565b92915050565b6000602082019050818103600083015261307a8184866127a5565b90509392505050565b6000602082019050818103600083015261309d81846127f7565b905092915050565b600060208201905081810360008301526130be81612830565b9050919050565b600060208201905081810360008301526130de81612896565b9050919050565b600060208201905081810360008301526130fe816128d6565b9050919050565b6000602082019050818103600083015261311e81612916565b9050919050565b6000602082019050818103600083015261313e81612956565b9050919050565b6000602082019050818103600083015261315e816129bc565b9050919050565b6000602082019050818103600083015261317e816129fc565b9050919050565b6000602082019050818103600083015261319e81612a62565b9050919050565b600060208201905081810360008301526131be81612aa2565b9050919050565b600060208201905081810360008301526131de81612ae2565b9050919050565b600060208201905081810360008301526131fe81612b22565b9050919050565b6000602082019050818103600083015261321e81612b62565b9050919050565b6000602082019050818103600083015261323e81612ba2565b9050919050565b6000602082019050818103600083015261325e81612be2565b9050919050565b6000602082019050818103600083015261327e81612c22565b9050919050565b6000602082019050818103600083015261329e81612c62565b9050919050565b600060208201905081810360008301526132be81612ca2565b9050919050565b600060208201905081810360008301526132de81612d08565b9050919050565b600060208201905081810360008301526132fe81612d48565b9050919050565b600060208201905061331a6000830184612d88565b92915050565b6000808335600160200384360303811261333957600080fd5b80840192508235915067ffffffffffffffff82111561335757600080fd5b60208301925060018202360383131561336f57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133f882613504565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506134ff8261361c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353982613540565b9050919050565b600061354b82613504565b9050919050565b600061355d826134f1565b9050919050565b82818337600083830152505050565b60005b83811015613591578082015181840152602081019050613576565b838111156135a0576000848401525b50505050565b60006135b1826135ea565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f58261360f565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061362d5761362c6135fc565b5b50565b613639816133ed565b811461364457600080fd5b50565b613650816133ff565b811461365b57600080fd5b50565b613667816134bb565b811461367257600080fd5b50565b61367e816134c5565b811461368957600080fd5b50565b6003811061369957600080fd5b50565b6136a581613524565b81146136b057600080fd5b5056fea2646970667358221220d5c9f5b6d4e12c49170d8830f9459ebc2386434f550d65bae2bbc0fcfbacfb6264736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/GraphTokenLockManager.json b/packages/token-distribution/deployments/goerli/GraphTokenLockManager.json new file mode 100644 index 000000000..4bf8fa8a5 --- /dev/null +++ b/packages/token-distribution/deployments/goerli/GraphTokenLockManager.json @@ -0,0 +1,926 @@ +{ + "address": "0x9a7a54e86560f4304d8862Ea00F45D1090c59ac8", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x8c4c0ac0ca63577d5313dd7d57378339f67a70794f321461c4ba76fcfffe08e7", + "receipt": { + "to": null, + "from": "0xEfc519BEd6a43a14f1BBBbA9e796C4931f7A5540", + "contractAddress": "0x9a7a54e86560f4304d8862Ea00F45D1090c59ac8", + "transactionIndex": 5, + "gasUsed": "3166280", + "logsBloom": "0x02000020000000800000000000000000000004000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000400000000000000000020000000000000400000800000000000000000101000000000000400000000010000000000000000000000000000000000000000000080000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1ab85c22e1dcdc6aa782224b150da9f6ef4e0a259f51db36ca20689d67c9a6fe", + "transactionHash": "0x8c4c0ac0ca63577d5313dd7d57378339f67a70794f321461c4ba76fcfffe08e7", + "logs": [ + { + "transactionIndex": 5, + "blockNumber": 7370681, + "transactionHash": "0x8c4c0ac0ca63577d5313dd7d57378339f67a70794f321461c4ba76fcfffe08e7", + "address": "0x9a7a54e86560f4304d8862Ea00F45D1090c59ac8", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000efc519bed6a43a14f1bbbba9e796c4931f7a5540" + ], + "data": "0x", + "logIndex": 3, + "blockHash": "0x1ab85c22e1dcdc6aa782224b150da9f6ef4e0a259f51db36ca20689d67c9a6fe" + }, + { + "transactionIndex": 5, + "blockNumber": 7370681, + "transactionHash": "0x8c4c0ac0ca63577d5313dd7d57378339f67a70794f321461c4ba76fcfffe08e7", + "address": "0x9a7a54e86560f4304d8862Ea00F45D1090c59ac8", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x000000000000000000000000bbceb991e59a4e53dfdbd4a4b1843de1830017b3" + ], + "data": "0x", + "logIndex": 4, + "blockHash": "0x1ab85c22e1dcdc6aa782224b150da9f6ef4e0a259f51db36ca20689d67c9a6fe" + } + ], + "blockNumber": 7370681, + "cumulativeGasUsed": "3503839", + "status": 1, + "byzantium": true + }, + "args": [ + "0x5c946740441C12510a167B447B7dE565C20b9E3C", + "0xbBCeB991e59a4E53DfDbD4a4B1843de1830017B3" + ], + "solcInputHash": "3c1e469b4f9ba208577ab7c230900006", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address)\":{\"params\":{\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 private _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSignature(\\n \\\"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\\\",\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\\n external\\n override\\n onlyOwner\\n {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solium-disable-next-line security/no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x0384d62cb600eb4128baacf5bca60ea2cb0b68d2d013479daef65ed5f15446ef\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n// Based on https://eips.ethereum.org/EIPS/eip-1167\\ncontract MinimalProxyFactory is Ownable {\\n // -- Events --\\n\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\\n }\\n\\n /**\\n * @notice Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(\\n bytes32 _salt,\\n address _implementation,\\n bytes memory _data\\n ) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @notice Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x8aa3d50e714f92dc0ed6cc6d88fa8a18c948493103928f6092f98815b2c046ca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003c9338038062003c9383398181016040528101906200003791906200039c565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004e7565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b505062000596565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001f26200034560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200024b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024290620004c5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b590620004a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000815190506200037f8162000562565b92915050565b60008151905062000396816200057c565b92915050565b60008060408385031215620003b057600080fd5b6000620003c08582860162000385565b9250506020620003d3858286016200036e565b9150509250929050565b6000620003ec60198362000509565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006200042e60208362000509565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200047060148362000509565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004be81620003dd565b9050919050565b60006020820190508181036000830152620004e0816200041f565b9050919050565b60006020820190508181036000830152620005028162000461565b9050919050565b600082825260208201905092915050565b6000620005278262000542565b9050919050565b60006200053b826200051a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200056d816200051a565b81146200057957600080fd5b50565b62000587816200052e565b81146200059357600080fd5b50565b6136ed80620005a66000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address)": { + "params": { + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3316, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3318, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)1964_storage" + }, + { + "astId": 3320, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3322, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1045" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1045": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)1964_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 1963, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)1699_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)1699_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 1694, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 1698, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/GraphTokenLockWallet-Testnet.json b/packages/token-distribution/deployments/goerli/GraphTokenLockWallet-Testnet.json new file mode 100644 index 000000000..0f088084b --- /dev/null +++ b/packages/token-distribution/deployments/goerli/GraphTokenLockWallet-Testnet.json @@ -0,0 +1,1101 @@ +{ + "address": "0xc93df24c3A1ebeCcd0e5D41198460081CFB38c49", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xc82db94de89d7e695ffb90299b1501f199d5250c3b47bb755f5bb05c033632c0", + "receipt": { + "to": null, + "from": "0xB15599AC1261C4828Ac7E66383ae520655d3D300", + "contractAddress": "0xc93df24c3A1ebeCcd0e5D41198460081CFB38c49", + "transactionIndex": 19, + "gasUsed": "3942206", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x78bdbf41774296aeb2563b0fb9e2ed3985a50428bf22c22f7c92e289963f92f2", + "transactionHash": "0xc82db94de89d7e695ffb90299b1501f199d5250c3b47bb755f5bb05c033632c0", + "logs": [], + "blockNumber": 9345441, + "cumulativeGasUsed": "10310545", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506146bb806100206000396000f3fe6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610b93578063e8dda6f514610bbc578063e97d87d514610be7578063ebbab99214610c12578063f2fde38b14610c3d578063fc0c546a14610c6657610295565b8063bc0163c114610ac0578063bd896dcb14610aeb578063ce845d1d14610b14578063d0ebdbe714610b3f578063d18e81b314610b6857610295565b806391f7cfb9116100fd57806391f7cfb9146109ff578063a4caeb4214610a2a578063b0d1818c14610a55578063b470aade14610a7e578063b6549f7514610aa957610295565b806386d00e021461095057806386d1a69f1461097b578063872a7810146109925780638a5bdf5c146109bd5780638da5cb5b146109d457610295565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108765780635b940081146108a157806360e79944146108cc578063715018a6146108e357806378e97925146108fa5780637bdf05af1461092557610295565b8063392e53cd1461079f578063398057a3146107ca57806344b1231f146107f557806345d30a1714610820578063481c6a751461084b57610295565b80632a627814116102195780632a627814146106dc5780632bc9ed02146106f35780633197cbb61461071e57806337aeb0861461074957806338af3eed1461077457610295565b8063029c6c9f1461061957806306040618146106445780630b80f7771461066f5780630dff24d5146106865780630fb5a6b4146106b157610295565b36610295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028c90613fb9565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c90614199565b60405180910390fd5b60003414610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035f90613fd9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103e99190613f2b565b60206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043991906131a5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a290614299565b60405180910390fd5b60006104b5610c91565b9050610506826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d43565b506001600281111561051457fe5b603b60009054906101000a900460ff16600281111561052f57fe5b141561061557600061053f610c91565b90508181101561058157600061055e8284610d8d90919063ffffffff16565b905061057581603f54610ddd90919063ffffffff16565b603f81905550506105c7565b60006105968383610d8d90919063ffffffff16565b9050603f548110156105bc576105b781603f54610d8d90919063ffffffff16565b6105bf565b60005b603f81905550505b6105cf610e32565b603f541115610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060a906141f9565b60405180910390fd5b505b5050005b34801561062557600080fd5b5061062e610ea1565b60405161063b9190614439565b60405180910390f35b34801561065057600080fd5b50610659610ebf565b6040516106669190614439565b60405180910390f35b34801561067b57600080fd5b50610684610efa565b005b34801561069257600080fd5b5061069b611067565b6040516106a89190614439565b60405180910390f35b3480156106bd57600080fd5b506106c66110ae565b6040516106d39190614439565b60405180910390f35b3480156106e857600080fd5b506106f16110cc565b005b3480156106ff57600080fd5b50610708611331565b6040516107159190613f10565b60405180910390f35b34801561072a57600080fd5b50610733611344565b6040516107409190614439565b60405180910390f35b34801561075557600080fd5b5061075e61134a565b60405161076b9190614439565b60405180910390f35b34801561078057600080fd5b50610789611350565b6040516107969190613ea3565b60405180910390f35b3480156107ab57600080fd5b506107b4611376565b6040516107c19190613f10565b60405180910390f35b3480156107d657600080fd5b506107df611389565b6040516107ec9190614439565b60405180910390f35b34801561080157600080fd5b5061080a610e32565b6040516108179190614439565b60405180910390f35b34801561082c57600080fd5b5061083561138f565b6040516108429190614439565b60405180910390f35b34801561085757600080fd5b50610860611395565b60405161086d9190613f61565b60405180910390f35b34801561088257600080fd5b5061088b6113bb565b6040516108989190613f10565b60405180910390f35b3480156108ad57600080fd5b506108b66113ce565b6040516108c39190614439565b60405180910390f35b3480156108d857600080fd5b506108e16114d9565b005b3480156108ef57600080fd5b506108f861171f565b005b34801561090657600080fd5b5061090f61186b565b60405161091c9190614439565b60405180910390f35b34801561093157600080fd5b5061093a611871565b6040516109479190614439565b60405180910390f35b34801561095c57600080fd5b506109656118ad565b6040516109729190614439565b60405180910390f35b34801561098757600080fd5b506109906118b3565b005b34801561099e57600080fd5b506109a7611a8f565b6040516109b49190613f7c565b60405180910390f35b3480156109c957600080fd5b506109d2611aa2565b005b3480156109e057600080fd5b506109e9611b7b565b6040516109f69190613ea3565b60405180910390f35b348015610a0b57600080fd5b50610a14611ba4565b604051610a219190614439565b60405180910390f35b348015610a3657600080fd5b50610a3f611c02565b604051610a4c9190614439565b60405180910390f35b348015610a6157600080fd5b50610a7c6004803603810190610a779190613328565b611c08565b005b348015610a8a57600080fd5b50610a93611e07565b604051610aa09190614439565b60405180910390f35b348015610ab557600080fd5b50610abe611e2a565b005b348015610acc57600080fd5b50610ad56120c2565b604051610ae29190614439565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d91906131ce565b6120f4565b005b348015610b2057600080fd5b50610b29610c91565b604051610b369190614439565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061317c565b61211c565b005b348015610b7457600080fd5b50610b7d6121b6565b604051610b8a9190614439565b60405180910390f35b348015610b9f57600080fd5b50610bba6004803603810190610bb5919061317c565b6121be565b005b348015610bc857600080fd5b50610bd1612339565b604051610bde9190614439565b60405180910390f35b348015610bf357600080fd5b50610bfc61233f565b604051610c099190614439565b60405180910390f35b348015610c1e57600080fd5b50610c27612345565b604051610c349190614439565b60405180910390f35b348015610c4957600080fd5b50610c646004803603810190610c5f919061317c565b612367565b005b348015610c7257600080fd5b50610c7b612522565b604051610c889190613f46565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cee9190613ea3565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613351565b905090565b6060610d8583836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b600082821115610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc9906140f9565b60405180910390fd5b818303905092915050565b600080828401905083811015610e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1f90614079565b60405180910390fd5b8091505092915050565b6000600280811115610e4057fe5b603b60009054906101000a900460ff166002811115610e5b57fe5b1415610e6b576035549050610e9e565b6000603a54118015610e855750603a54610e836121b6565b105b15610e935760009050610e9e565b610e9b611ba4565b90505b90565b6000610eba60385460355461256090919063ffffffff16565b905090565b6000610ef56001610ee7610ed1611e07565b610ed9611871565b61256090919063ffffffff16565b610ddd90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7f90614259565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514610fde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fd5906140d9565b60405180910390fd5b611039610fe9611b7b565b610ff1610c91565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611072610c91565b9050600061107e6120c2565b9050808211156110a45761109b8183610d8d90919063ffffffff16565b925050506110ab565b6000925050505b90565b60006110c7603654603754610d8d90919063ffffffff16565b905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461115c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115390614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111c657600080fd5b505afa1580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061120391906132be565b905060005b815181101561130157603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061125b57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b81526004016112a1929190613ee7565b602060405180830381600087803b1580156112bb57600080fd5b505af11580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f391906132ff565b508080600101915050611208565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156113dc57fe5b603b60009054906101000a900460ff1660028111156113f757fe5b141561140c5761140561263c565b90506114d6565b600060395411801561142657506039546114246121b6565b105b1561143457600090506114d6565b6001600281111561144157fe5b603b60009054906101000a900460ff16600281111561145c57fe5b14801561146b57506000603a54115b801561147f5750603a5461147d6121b6565b105b1561148d57600090506114d6565b60006114bf603f546114b1603c546114a3611ba4565b610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b90506114d26114cc610c91565b826126f6565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115d357600080fd5b505afa1580156115e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061161091906132be565b905060005b81518110156116ef57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061166857fe5b602002602001015160006040518363ffffffff1660e01b815260040161168f929190613ebe565b602060405180830381600087803b1580156116a957600080fd5b505af11580156116bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e191906132ff565b508080600101915050611615565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a490614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b60008061187c6121b6565b905060365481116118915760009150506118aa565b6118a660365482610d8d90919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90614359565b60405180910390fd5b600061194d6113ce565b905060008111611992576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611989906143b9565b60405180910390fd5b6119a781603c54610ddd90919063ffffffff16565b603c81905550611a1c603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611a849190614439565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2990614359565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611baf6121b6565b9050603654811015611bc5576000915050611bff565b603754811115611bda57603554915050611bff565b611bfb611be5610ea1565b611bed612345565b61270f90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8f90614359565b60405180910390fd5b60008111611cdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd2906141d9565b60405180910390fd5b80611ce4611067565b1015611d25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1c906142d9565b60405180910390fd5b611d94603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611dfc9190614439565b60405180910390a250565b6000611e25603854611e176110ae565b61256090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90614259565b60405180910390fd5b60016002811115611ec557fe5b603b60009054906101000a900460ff166002811115611ee057fe5b14611f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1790614319565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90614419565b60405180910390fd5b6000611f94611f83610e32565b603554610d8d90919063ffffffff16565b905060008111611fd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd090614099565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061204f612006611b7b565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516120b79190614439565b60405180910390a250565b60006120ef603d546120e1603c54603554610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b905090565b6121068a8a8a8a8a8a8a8a8a8a61277f565b61210f8b612c09565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146121aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a190614259565b60405180910390fd5b6121b381612c09565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461224e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224590614359565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b590614179565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d8160405161232e9190613ea3565b60405180910390a150565b603f5481565b60395481565b60006123626001612354610ebf565b610d8d90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ec90614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245c90614059565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606125578484600085612d87565b90509392505050565b60008082116125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259b90614159565b60405180910390fd5b8183816125ad57fe5b04905092915050565b6126378363a9059cbb60e01b84846040516024016125d5929190613ee7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612e9c565b505050565b60008060395411801561265757506039546126556121b6565b105b1561266557600090506126f3565b6001600281111561267257fe5b603b60009054906101000a900460ff16600281111561268d57fe5b14801561269c57506000603a54115b80156126b05750603a546126ae6121b6565b105b156126be57600090506126f3565b60006126dc603c546126ce611ba4565b610d8d90919063ffffffff16565b90506126ef6126e9610c91565b826126f6565b9150505b90565b60008183106127055781612707565b825b905092915050565b6000808314156127225760009050612779565b600082840290508284828161273357fe5b0414612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90614239565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff16156127cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c6906142f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561283f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612836906140b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128a6906143f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561291f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612916906143d9565b60405180910390fd5b60008711612962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295990614139565b60405180910390fd5b60008614156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299d90614279565b60405180910390fd5b8486106129e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129df90614019565b60405180910390fd5b6001841015612a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2390614219565b60405180910390fd5b60006002811115612a3957fe5b816002811115612a4557fe5b1415612a86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7d90614039565b60405180910390fd5b848310612ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612abf90614379565b60405180910390fd5b848210612b0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0190613ff9565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612b2e8a612f63565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612bf857fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7090614339565b60405180910390fd5b612c8281613001565b612cc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb8906141b9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015612dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dc390614119565b60405180910390fd5b612dd585613001565b612e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0b906142b9565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051612e3e9190613e8c565b60006040518083038185875af1925050503d8060008114612e7b576040519150601f19603f3d011682016040523d82523d6000602084013e612e80565b606091505b5091509150612e90828286613014565b92505050949350505050565b6060612efe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b9050600081511115612f5e5780806020019051810190612f1e91906132ff565b612f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5490614399565b60405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b6060831561302457829050613074565b6000835111156130375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b9190613f97565b60405180910390fd5b9392505050565b60008135905061308a81614630565b92915050565b60008151905061309f81614630565b92915050565b600082601f8301126130b657600080fd5b81516130c96130c482614485565b614454565b915081818352602084019350602081019050838560208402820111156130ee57600080fd5b60005b8381101561311e57816131048882613090565b8452602084019350602083019250506001810190506130f1565b5050505092915050565b60008151905061313781614647565b92915050565b60008135905061314c8161465e565b92915050565b6000813590506131618161466e565b92915050565b6000815190506131768161466e565b92915050565b60006020828403121561318e57600080fd5b600061319c8482850161307b565b91505092915050565b6000602082840312156131b757600080fd5b60006131c584828501613090565b91505092915050565b60008060008060008060008060008060006101608c8e0312156131f057600080fd5b60006131fe8e828f0161307b565b9b5050602061320f8e828f0161307b565b9a505060406132208e828f0161307b565b99505060606132318e828f0161307b565b98505060806132428e828f01613152565b97505060a06132538e828f01613152565b96505060c06132648e828f01613152565b95505060e06132758e828f01613152565b9450506101006132878e828f01613152565b9350506101206132998e828f01613152565b9250506101406132ab8e828f0161313d565b9150509295989b509295989b9093969950565b6000602082840312156132d057600080fd5b600082015167ffffffffffffffff8111156132ea57600080fd5b6132f6848285016130a5565b91505092915050565b60006020828403121561331157600080fd5b600061331f84828501613128565b91505092915050565b60006020828403121561333a57600080fd5b600061334884828501613152565b91505092915050565b60006020828403121561336357600080fd5b600061337184828501613167565b91505092915050565b613383816144e3565b82525050565b613392816144f5565b82525050565b6133a181614501565b82525050565b60006133b2826144b1565b6133bc81856144c7565b93506133cc8185602086016145d6565b80840191505092915050565b6133e18161456a565b82525050565b6133f08161458e565b82525050565b6133ff816145b2565b82525050565b61340e816145c4565b82525050565b600061341f826144bc565b61342981856144d2565b93506134398185602086016145d6565b6134428161460b565b840191505092915050565b600061345a6008836144d2565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b600061349a601b836144d2565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b60006134da6022836144d2565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135406015836144d2565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b6000613580601e836144d2565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006135c06026836144d2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613626601b836144d2565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000613666601c836144d2565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006136a66014836144d2565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006136e6601f836144d2565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613726601e836144d2565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006137666026836144d2565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cc601d836144d2565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b600061380c601a836144d2565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b600061384c6011836144d2565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b600061388c6013836144d2565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b60006138cc601a836144d2565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b600061390c6015836144d2565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b600061394c6029836144d2565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b60006139b2601f836144d2565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b60006139f26021836144d2565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a586020836144d2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613a986016836144d2565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613ad86015836144d2565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613b18601d836144d2565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613b586024836144d2565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bbe6013836144d2565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613bfe6019836144d2565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613c3e6017836144d2565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613c7e6005836144d2565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613cbe602a836144d2565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d24602a836144d2565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d8a601e836144d2565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b6000613dca6014836144d2565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613e0a601a836144d2565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000613e4a600f836144d2565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b613e8681614560565b82525050565b6000613e9882846133a7565b915081905092915050565b6000602082019050613eb8600083018461337a565b92915050565b6000604082019050613ed3600083018561337a565b613ee06020830184613405565b9392505050565b6000604082019050613efc600083018561337a565b613f096020830184613e7d565b9392505050565b6000602082019050613f256000830184613389565b92915050565b6000602082019050613f406000830184613398565b92915050565b6000602082019050613f5b60008301846133d8565b92915050565b6000602082019050613f7660008301846133e7565b92915050565b6000602082019050613f9160008301846133f6565b92915050565b60006020820190508181036000830152613fb18184613414565b905092915050565b60006020820190508181036000830152613fd28161344d565b9050919050565b60006020820190508181036000830152613ff28161348d565b9050919050565b60006020820190508181036000830152614012816134cd565b9050919050565b6000602082019050818103600083015261403281613533565b9050919050565b6000602082019050818103600083015261405281613573565b9050919050565b60006020820190508181036000830152614072816135b3565b9050919050565b6000602082019050818103600083015261409281613619565b9050919050565b600060208201905081810360008301526140b281613659565b9050919050565b600060208201905081810360008301526140d281613699565b9050919050565b600060208201905081810360008301526140f2816136d9565b9050919050565b6000602082019050818103600083015261411281613719565b9050919050565b6000602082019050818103600083015261413281613759565b9050919050565b60006020820190508181036000830152614152816137bf565b9050919050565b60006020820190508181036000830152614172816137ff565b9050919050565b600060208201905081810360008301526141928161383f565b9050919050565b600060208201905081810360008301526141b28161387f565b9050919050565b600060208201905081810360008301526141d2816138bf565b9050919050565b600060208201905081810360008301526141f2816138ff565b9050919050565b600060208201905081810360008301526142128161393f565b9050919050565b60006020820190508181036000830152614232816139a5565b9050919050565b60006020820190508181036000830152614252816139e5565b9050919050565b6000602082019050818103600083015261427281613a4b565b9050919050565b6000602082019050818103600083015261429281613a8b565b9050919050565b600060208201905081810360008301526142b281613acb565b9050919050565b600060208201905081810360008301526142d281613b0b565b9050919050565b600060208201905081810360008301526142f281613b4b565b9050919050565b6000602082019050818103600083015261431281613bb1565b9050919050565b6000602082019050818103600083015261433281613bf1565b9050919050565b6000602082019050818103600083015261435281613c31565b9050919050565b6000602082019050818103600083015261437281613c71565b9050919050565b6000602082019050818103600083015261439281613cb1565b9050919050565b600060208201905081810360008301526143b281613d17565b9050919050565b600060208201905081810360008301526143d281613d7d565b9050919050565b600060208201905081810360008301526143f281613dbd565b9050919050565b6000602082019050818103600083015261441281613dfd565b9050919050565b6000602082019050818103600083015261443281613e3d565b9050919050565b600060208201905061444e6000830184613e7d565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561447b5761447a614609565b5b8060405250919050565b600067ffffffffffffffff8211156144a05761449f614609565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006144ee82614540565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061453b8261461c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006145758261457c565b9050919050565b600061458782614540565b9050919050565b6000614599826145a0565b9050919050565b60006145ab82614540565b9050919050565b60006145bd8261452d565b9050919050565b60006145cf82614560565b9050919050565b60005b838110156145f45780820151818401526020810190506145d9565b83811115614603576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061462d5761462c614609565b5b50565b614639816144e3565b811461464457600080fd5b50565b614650816144f5565b811461465b57600080fd5b50565b6003811061466b57600080fd5b50565b61467781614560565b811461468257600080fd5b5056fea264697066735822122013f3b022e354ddf49f7a28727f309f858a5cbdf70833a2e54da3c1a482b7073164736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610b93578063e8dda6f514610bbc578063e97d87d514610be7578063ebbab99214610c12578063f2fde38b14610c3d578063fc0c546a14610c6657610295565b8063bc0163c114610ac0578063bd896dcb14610aeb578063ce845d1d14610b14578063d0ebdbe714610b3f578063d18e81b314610b6857610295565b806391f7cfb9116100fd57806391f7cfb9146109ff578063a4caeb4214610a2a578063b0d1818c14610a55578063b470aade14610a7e578063b6549f7514610aa957610295565b806386d00e021461095057806386d1a69f1461097b578063872a7810146109925780638a5bdf5c146109bd5780638da5cb5b146109d457610295565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108765780635b940081146108a157806360e79944146108cc578063715018a6146108e357806378e97925146108fa5780637bdf05af1461092557610295565b8063392e53cd1461079f578063398057a3146107ca57806344b1231f146107f557806345d30a1714610820578063481c6a751461084b57610295565b80632a627814116102195780632a627814146106dc5780632bc9ed02146106f35780633197cbb61461071e57806337aeb0861461074957806338af3eed1461077457610295565b8063029c6c9f1461061957806306040618146106445780630b80f7771461066f5780630dff24d5146106865780630fb5a6b4146106b157610295565b36610295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028c90613fb9565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c90614199565b60405180910390fd5b60003414610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035f90613fd9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103e99190613f2b565b60206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043991906131a5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a290614299565b60405180910390fd5b60006104b5610c91565b9050610506826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d43565b506001600281111561051457fe5b603b60009054906101000a900460ff16600281111561052f57fe5b141561061557600061053f610c91565b90508181101561058157600061055e8284610d8d90919063ffffffff16565b905061057581603f54610ddd90919063ffffffff16565b603f81905550506105c7565b60006105968383610d8d90919063ffffffff16565b9050603f548110156105bc576105b781603f54610d8d90919063ffffffff16565b6105bf565b60005b603f81905550505b6105cf610e32565b603f541115610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060a906141f9565b60405180910390fd5b505b5050005b34801561062557600080fd5b5061062e610ea1565b60405161063b9190614439565b60405180910390f35b34801561065057600080fd5b50610659610ebf565b6040516106669190614439565b60405180910390f35b34801561067b57600080fd5b50610684610efa565b005b34801561069257600080fd5b5061069b611067565b6040516106a89190614439565b60405180910390f35b3480156106bd57600080fd5b506106c66110ae565b6040516106d39190614439565b60405180910390f35b3480156106e857600080fd5b506106f16110cc565b005b3480156106ff57600080fd5b50610708611331565b6040516107159190613f10565b60405180910390f35b34801561072a57600080fd5b50610733611344565b6040516107409190614439565b60405180910390f35b34801561075557600080fd5b5061075e61134a565b60405161076b9190614439565b60405180910390f35b34801561078057600080fd5b50610789611350565b6040516107969190613ea3565b60405180910390f35b3480156107ab57600080fd5b506107b4611376565b6040516107c19190613f10565b60405180910390f35b3480156107d657600080fd5b506107df611389565b6040516107ec9190614439565b60405180910390f35b34801561080157600080fd5b5061080a610e32565b6040516108179190614439565b60405180910390f35b34801561082c57600080fd5b5061083561138f565b6040516108429190614439565b60405180910390f35b34801561085757600080fd5b50610860611395565b60405161086d9190613f61565b60405180910390f35b34801561088257600080fd5b5061088b6113bb565b6040516108989190613f10565b60405180910390f35b3480156108ad57600080fd5b506108b66113ce565b6040516108c39190614439565b60405180910390f35b3480156108d857600080fd5b506108e16114d9565b005b3480156108ef57600080fd5b506108f861171f565b005b34801561090657600080fd5b5061090f61186b565b60405161091c9190614439565b60405180910390f35b34801561093157600080fd5b5061093a611871565b6040516109479190614439565b60405180910390f35b34801561095c57600080fd5b506109656118ad565b6040516109729190614439565b60405180910390f35b34801561098757600080fd5b506109906118b3565b005b34801561099e57600080fd5b506109a7611a8f565b6040516109b49190613f7c565b60405180910390f35b3480156109c957600080fd5b506109d2611aa2565b005b3480156109e057600080fd5b506109e9611b7b565b6040516109f69190613ea3565b60405180910390f35b348015610a0b57600080fd5b50610a14611ba4565b604051610a219190614439565b60405180910390f35b348015610a3657600080fd5b50610a3f611c02565b604051610a4c9190614439565b60405180910390f35b348015610a6157600080fd5b50610a7c6004803603810190610a779190613328565b611c08565b005b348015610a8a57600080fd5b50610a93611e07565b604051610aa09190614439565b60405180910390f35b348015610ab557600080fd5b50610abe611e2a565b005b348015610acc57600080fd5b50610ad56120c2565b604051610ae29190614439565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d91906131ce565b6120f4565b005b348015610b2057600080fd5b50610b29610c91565b604051610b369190614439565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061317c565b61211c565b005b348015610b7457600080fd5b50610b7d6121b6565b604051610b8a9190614439565b60405180910390f35b348015610b9f57600080fd5b50610bba6004803603810190610bb5919061317c565b6121be565b005b348015610bc857600080fd5b50610bd1612339565b604051610bde9190614439565b60405180910390f35b348015610bf357600080fd5b50610bfc61233f565b604051610c099190614439565b60405180910390f35b348015610c1e57600080fd5b50610c27612345565b604051610c349190614439565b60405180910390f35b348015610c4957600080fd5b50610c646004803603810190610c5f919061317c565b612367565b005b348015610c7257600080fd5b50610c7b612522565b604051610c889190613f46565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cee9190613ea3565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613351565b905090565b6060610d8583836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b600082821115610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc9906140f9565b60405180910390fd5b818303905092915050565b600080828401905083811015610e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1f90614079565b60405180910390fd5b8091505092915050565b6000600280811115610e4057fe5b603b60009054906101000a900460ff166002811115610e5b57fe5b1415610e6b576035549050610e9e565b6000603a54118015610e855750603a54610e836121b6565b105b15610e935760009050610e9e565b610e9b611ba4565b90505b90565b6000610eba60385460355461256090919063ffffffff16565b905090565b6000610ef56001610ee7610ed1611e07565b610ed9611871565b61256090919063ffffffff16565b610ddd90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7f90614259565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514610fde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fd5906140d9565b60405180910390fd5b611039610fe9611b7b565b610ff1610c91565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611072610c91565b9050600061107e6120c2565b9050808211156110a45761109b8183610d8d90919063ffffffff16565b925050506110ab565b6000925050505b90565b60006110c7603654603754610d8d90919063ffffffff16565b905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461115c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115390614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111c657600080fd5b505afa1580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061120391906132be565b905060005b815181101561130157603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061125b57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b81526004016112a1929190613ee7565b602060405180830381600087803b1580156112bb57600080fd5b505af11580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f391906132ff565b508080600101915050611208565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156113dc57fe5b603b60009054906101000a900460ff1660028111156113f757fe5b141561140c5761140561263c565b90506114d6565b600060395411801561142657506039546114246121b6565b105b1561143457600090506114d6565b6001600281111561144157fe5b603b60009054906101000a900460ff16600281111561145c57fe5b14801561146b57506000603a54115b801561147f5750603a5461147d6121b6565b105b1561148d57600090506114d6565b60006114bf603f546114b1603c546114a3611ba4565b610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b90506114d26114cc610c91565b826126f6565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115d357600080fd5b505afa1580156115e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061161091906132be565b905060005b81518110156116ef57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061166857fe5b602002602001015160006040518363ffffffff1660e01b815260040161168f929190613ebe565b602060405180830381600087803b1580156116a957600080fd5b505af11580156116bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e191906132ff565b508080600101915050611615565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a490614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b60008061187c6121b6565b905060365481116118915760009150506118aa565b6118a660365482610d8d90919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90614359565b60405180910390fd5b600061194d6113ce565b905060008111611992576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611989906143b9565b60405180910390fd5b6119a781603c54610ddd90919063ffffffff16565b603c81905550611a1c603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611a849190614439565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2990614359565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611baf6121b6565b9050603654811015611bc5576000915050611bff565b603754811115611bda57603554915050611bff565b611bfb611be5610ea1565b611bed612345565b61270f90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8f90614359565b60405180910390fd5b60008111611cdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd2906141d9565b60405180910390fd5b80611ce4611067565b1015611d25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1c906142d9565b60405180910390fd5b611d94603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611dfc9190614439565b60405180910390a250565b6000611e25603854611e176110ae565b61256090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90614259565b60405180910390fd5b60016002811115611ec557fe5b603b60009054906101000a900460ff166002811115611ee057fe5b14611f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1790614319565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90614419565b60405180910390fd5b6000611f94611f83610e32565b603554610d8d90919063ffffffff16565b905060008111611fd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd090614099565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061204f612006611b7b565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516120b79190614439565b60405180910390a250565b60006120ef603d546120e1603c54603554610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b905090565b6121068a8a8a8a8a8a8a8a8a8a61277f565b61210f8b612c09565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146121aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a190614259565b60405180910390fd5b6121b381612c09565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461224e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224590614359565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b590614179565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d8160405161232e9190613ea3565b60405180910390a150565b603f5481565b60395481565b60006123626001612354610ebf565b610d8d90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ec90614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245c90614059565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606125578484600085612d87565b90509392505050565b60008082116125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259b90614159565b60405180910390fd5b8183816125ad57fe5b04905092915050565b6126378363a9059cbb60e01b84846040516024016125d5929190613ee7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612e9c565b505050565b60008060395411801561265757506039546126556121b6565b105b1561266557600090506126f3565b6001600281111561267257fe5b603b60009054906101000a900460ff16600281111561268d57fe5b14801561269c57506000603a54115b80156126b05750603a546126ae6121b6565b105b156126be57600090506126f3565b60006126dc603c546126ce611ba4565b610d8d90919063ffffffff16565b90506126ef6126e9610c91565b826126f6565b9150505b90565b60008183106127055781612707565b825b905092915050565b6000808314156127225760009050612779565b600082840290508284828161273357fe5b0414612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90614239565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff16156127cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c6906142f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561283f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612836906140b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128a6906143f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561291f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612916906143d9565b60405180910390fd5b60008711612962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295990614139565b60405180910390fd5b60008614156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299d90614279565b60405180910390fd5b8486106129e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129df90614019565b60405180910390fd5b6001841015612a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2390614219565b60405180910390fd5b60006002811115612a3957fe5b816002811115612a4557fe5b1415612a86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7d90614039565b60405180910390fd5b848310612ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612abf90614379565b60405180910390fd5b848210612b0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0190613ff9565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612b2e8a612f63565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612bf857fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7090614339565b60405180910390fd5b612c8281613001565b612cc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb8906141b9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015612dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dc390614119565b60405180910390fd5b612dd585613001565b612e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0b906142b9565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051612e3e9190613e8c565b60006040518083038185875af1925050503d8060008114612e7b576040519150601f19603f3d011682016040523d82523d6000602084013e612e80565b606091505b5091509150612e90828286613014565b92505050949350505050565b6060612efe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b9050600081511115612f5e5780806020019051810190612f1e91906132ff565b612f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5490614399565b60405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b6060831561302457829050613074565b6000835111156130375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b9190613f97565b60405180910390fd5b9392505050565b60008135905061308a81614630565b92915050565b60008151905061309f81614630565b92915050565b600082601f8301126130b657600080fd5b81516130c96130c482614485565b614454565b915081818352602084019350602081019050838560208402820111156130ee57600080fd5b60005b8381101561311e57816131048882613090565b8452602084019350602083019250506001810190506130f1565b5050505092915050565b60008151905061313781614647565b92915050565b60008135905061314c8161465e565b92915050565b6000813590506131618161466e565b92915050565b6000815190506131768161466e565b92915050565b60006020828403121561318e57600080fd5b600061319c8482850161307b565b91505092915050565b6000602082840312156131b757600080fd5b60006131c584828501613090565b91505092915050565b60008060008060008060008060008060006101608c8e0312156131f057600080fd5b60006131fe8e828f0161307b565b9b5050602061320f8e828f0161307b565b9a505060406132208e828f0161307b565b99505060606132318e828f0161307b565b98505060806132428e828f01613152565b97505060a06132538e828f01613152565b96505060c06132648e828f01613152565b95505060e06132758e828f01613152565b9450506101006132878e828f01613152565b9350506101206132998e828f01613152565b9250506101406132ab8e828f0161313d565b9150509295989b509295989b9093969950565b6000602082840312156132d057600080fd5b600082015167ffffffffffffffff8111156132ea57600080fd5b6132f6848285016130a5565b91505092915050565b60006020828403121561331157600080fd5b600061331f84828501613128565b91505092915050565b60006020828403121561333a57600080fd5b600061334884828501613152565b91505092915050565b60006020828403121561336357600080fd5b600061337184828501613167565b91505092915050565b613383816144e3565b82525050565b613392816144f5565b82525050565b6133a181614501565b82525050565b60006133b2826144b1565b6133bc81856144c7565b93506133cc8185602086016145d6565b80840191505092915050565b6133e18161456a565b82525050565b6133f08161458e565b82525050565b6133ff816145b2565b82525050565b61340e816145c4565b82525050565b600061341f826144bc565b61342981856144d2565b93506134398185602086016145d6565b6134428161460b565b840191505092915050565b600061345a6008836144d2565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b600061349a601b836144d2565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b60006134da6022836144d2565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135406015836144d2565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b6000613580601e836144d2565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006135c06026836144d2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613626601b836144d2565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000613666601c836144d2565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006136a66014836144d2565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006136e6601f836144d2565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613726601e836144d2565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006137666026836144d2565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cc601d836144d2565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b600061380c601a836144d2565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b600061384c6011836144d2565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b600061388c6013836144d2565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b60006138cc601a836144d2565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b600061390c6015836144d2565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b600061394c6029836144d2565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b60006139b2601f836144d2565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b60006139f26021836144d2565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a586020836144d2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613a986016836144d2565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613ad86015836144d2565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613b18601d836144d2565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613b586024836144d2565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bbe6013836144d2565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613bfe6019836144d2565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613c3e6017836144d2565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613c7e6005836144d2565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613cbe602a836144d2565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d24602a836144d2565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d8a601e836144d2565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b6000613dca6014836144d2565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613e0a601a836144d2565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000613e4a600f836144d2565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b613e8681614560565b82525050565b6000613e9882846133a7565b915081905092915050565b6000602082019050613eb8600083018461337a565b92915050565b6000604082019050613ed3600083018561337a565b613ee06020830184613405565b9392505050565b6000604082019050613efc600083018561337a565b613f096020830184613e7d565b9392505050565b6000602082019050613f256000830184613389565b92915050565b6000602082019050613f406000830184613398565b92915050565b6000602082019050613f5b60008301846133d8565b92915050565b6000602082019050613f7660008301846133e7565b92915050565b6000602082019050613f9160008301846133f6565b92915050565b60006020820190508181036000830152613fb18184613414565b905092915050565b60006020820190508181036000830152613fd28161344d565b9050919050565b60006020820190508181036000830152613ff28161348d565b9050919050565b60006020820190508181036000830152614012816134cd565b9050919050565b6000602082019050818103600083015261403281613533565b9050919050565b6000602082019050818103600083015261405281613573565b9050919050565b60006020820190508181036000830152614072816135b3565b9050919050565b6000602082019050818103600083015261409281613619565b9050919050565b600060208201905081810360008301526140b281613659565b9050919050565b600060208201905081810360008301526140d281613699565b9050919050565b600060208201905081810360008301526140f2816136d9565b9050919050565b6000602082019050818103600083015261411281613719565b9050919050565b6000602082019050818103600083015261413281613759565b9050919050565b60006020820190508181036000830152614152816137bf565b9050919050565b60006020820190508181036000830152614172816137ff565b9050919050565b600060208201905081810360008301526141928161383f565b9050919050565b600060208201905081810360008301526141b28161387f565b9050919050565b600060208201905081810360008301526141d2816138bf565b9050919050565b600060208201905081810360008301526141f2816138ff565b9050919050565b600060208201905081810360008301526142128161393f565b9050919050565b60006020820190508181036000830152614232816139a5565b9050919050565b60006020820190508181036000830152614252816139e5565b9050919050565b6000602082019050818103600083015261427281613a4b565b9050919050565b6000602082019050818103600083015261429281613a8b565b9050919050565b600060208201905081810360008301526142b281613acb565b9050919050565b600060208201905081810360008301526142d281613b0b565b9050919050565b600060208201905081810360008301526142f281613b4b565b9050919050565b6000602082019050818103600083015261431281613bb1565b9050919050565b6000602082019050818103600083015261433281613bf1565b9050919050565b6000602082019050818103600083015261435281613c31565b9050919050565b6000602082019050818103600083015261437281613c71565b9050919050565b6000602082019050818103600083015261439281613cb1565b9050919050565b600060208201905081810360008301526143b281613d17565b9050919050565b600060208201905081810360008301526143d281613d7d565b9050919050565b600060208201905081810360008301526143f281613dbd565b9050919050565b6000602082019050818103600083015261441281613dfd565b9050919050565b6000602082019050818103600083015261443281613e3d565b9050919050565b600060208201905061444e6000830184613e7d565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561447b5761447a614609565b5b8060405250919050565b600067ffffffffffffffff8211156144a05761449f614609565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006144ee82614540565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061453b8261461c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006145758261457c565b9050919050565b600061458782614540565b9050919050565b6000614599826145a0565b9050919050565b60006145ab82614540565b9050919050565b60006145bd8261452d565b9050919050565b60006145cf82614560565b9050919050565b60005b838110156145f45780820151818401526020810190506145d9565b83811115614603576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061462d5761462c614609565b5b50565b614639816144e3565b811461464457600080fd5b50565b614650816144f5565b811461465b57600080fd5b50565b6003811061466b57600080fd5b50565b61467781614560565b811461468257600080fd5b5056fea264697066735822122013f3b022e354ddf49f7a28727f309f858a5cbdf70833a2e54da3c1a482b7073164736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6797, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 6802, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 3244, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "51", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 3246, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "52", + "type": "t_address" + }, + { + "astId": 3248, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "53", + "type": "t_uint256" + }, + { + "astId": 3250, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "54", + "type": "t_uint256" + }, + { + "astId": 3252, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "55", + "type": "t_uint256" + }, + { + "astId": 3254, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 3256, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "57", + "type": "t_uint256" + }, + { + "astId": 3258, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "58", + "type": "t_uint256" + }, + { + "astId": 3260, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "59", + "type": "t_enum(Revocability)5096" + }, + { + "astId": 3262, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3264, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3266, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3268, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "60", + "type": "t_uint256" + }, + { + "astId": 3270, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "61", + "type": "t_uint256" + }, + { + "astId": 4692, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "62", + "type": "t_contract(IGraphTokenLockManager)5278" + }, + { + "astId": 4694, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "63", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)5278": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)5096": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/GraphTokenLockWallet.json b/packages/token-distribution/deployments/goerli/GraphTokenLockWallet.json new file mode 100644 index 000000000..589c2c59a --- /dev/null +++ b/packages/token-distribution/deployments/goerli/GraphTokenLockWallet.json @@ -0,0 +1,1083 @@ +{ + "address": "0xbBCeB991e59a4E53DfDbD4a4B1843de1830017B3", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xb079f74185692c4d4293de429f6ab2e9fcdcfe0914cd05f4b6e7b3971f9fde30", + "receipt": { + "to": null, + "from": "0xEfc519BEd6a43a14f1BBBbA9e796C4931f7A5540", + "contractAddress": "0xbBCeB991e59a4E53DfDbD4a4B1843de1830017B3", + "transactionIndex": 21, + "gasUsed": "3482943", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9700265b7456a3d8c07977f2e2dbbcd14235ef873425f011d340bbb8be4b20a0", + "transactionHash": "0xb079f74185692c4d4293de429f6ab2e9fcdcfe0914cd05f4b6e7b3971f9fde30", + "logs": [], + "blockNumber": 7370680, + "cumulativeGasUsed": "11418126", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "3c1e469b4f9ba208577ab7c230900006", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n Ownable.initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0x21a1dae4105ba9ff6d9bc38bf983ee853976346562fa284f4b67a3c7ca91a2bf\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n uint256 private constant MAX_UINT256 = 2**256 - 1;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) private {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], MAX_UINT256);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5efc82d408fe81193664e67d614ca6299eafb00163ecc7819fad77cf0d35a2eb\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xc93c7362ac4d74b624b48517985f92c277ce90ae6e5ccb706e70a61af5752077\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613e61806100206000396000f3fe6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 4749, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2578, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "1", + "type": "t_contract(IERC20)1045" + }, + { + "astId": 2580, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 2582, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 2584, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 2586, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 2588, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 2590, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "7", + "type": "t_uint256" + }, + { + "astId": 2592, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 2594, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "9", + "type": "t_enum(Revocability)4426" + }, + { + "astId": 2596, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2598, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2600, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2602, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "10", + "type": "t_uint256" + }, + { + "astId": 2604, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "11", + "type": "t_uint256" + }, + { + "astId": 4021, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "12", + "type": "t_contract(IGraphTokenLockManager)4608" + }, + { + "astId": 4023, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "13", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1045": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)4608": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)4426": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/L1GraphTokenLockTransferTool.json b/packages/token-distribution/deployments/goerli/L1GraphTokenLockTransferTool.json new file mode 100644 index 000000000..1af15ddf8 --- /dev/null +++ b/packages/token-distribution/deployments/goerli/L1GraphTokenLockTransferTool.json @@ -0,0 +1,612 @@ +{ + "address": "0xa725CF32c367778CFF2ba7089Ab4e941BDD88612", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Implementation", + "type": "address" + }, + { + "internalType": "contract ITokenGateway", + "name": "_l1Gateway", + "type": "address" + }, + { + "internalType": "address payable", + "name": "_staking", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHPulled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Beneficiary", + "type": "address" + } + ], + "name": "L2BeneficiarySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1LockManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + } + ], + "name": "L2LockManagerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + } + ], + "name": "L2WalletAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1WalletOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2WalletOwner", + "type": "address" + } + ], + "name": "L2WalletOwnerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedFundsSentToL2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenLock", + "type": "address" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_l2Beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSubmissionCost", + "type": "uint256" + } + ], + "name": "depositToL2Locked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "graphToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Gateway", + "outputs": [ + { + "internalType": "contract ITokenGateway", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2Beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2LockManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletAddressSetManually", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenLock", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "pullETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1LockManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2LockManager", + "type": "address" + } + ], + "name": "setL2LockManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Wallet", + "type": "address" + } + ], + "name": "setL2WalletAddressManually", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1WalletOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WalletOwner", + "type": "address" + } + ], + "name": "setL2WalletOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "staking", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenLockETHBalances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_destination", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x7297670fbbf9f1c014aac93fa0219522c079bdd0ad4bb16c75a204ba97b1bc81" +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/solcInputs/3c1e469b4f9ba208577ab7c230900006.json b/packages/token-distribution/deployments/goerli/solcInputs/3c1e469b4f9ba208577ab7c230900006.json new file mode 100644 index 000000000..276324157 --- /dev/null +++ b/packages/token-distribution/deployments/goerli/solcInputs/3c1e469b4f9ba208577ab7c230900006.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) private {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], MAX_UINT256);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n Ownable.initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/StakingMock.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/Stakes.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(\n Stakes.Indexer storage stake,\n uint256 _tokens,\n uint256 _period\n ) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(Stakes.Indexer memory stake, uint256 _delegatedCapacity)\n internal\n pure\n returns (uint256)\n {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "contracts/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @dev Contract Constructor.\n * @param _initialSupply Initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\n\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n// Based on https://eips.ethereum.org/EIPS/eip-1167\ncontract MinimalProxyFactory is Ownable {\n // -- Events --\n\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\n }\n\n /**\n * @notice Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(\n bytes32 _salt,\n address _implementation,\n bytes memory _data\n ) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @notice Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 private _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSignature(\n \"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\",\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\n external\n override\n onlyOwner\n {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n * \n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n Ownable.initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json b/packages/token-distribution/deployments/goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json new file mode 100644 index 000000000..4eda754ae --- /dev/null +++ b/packages/token-distribution/deployments/goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json @@ -0,0 +1,152 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMathUpgradeable {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/arbitrum/ITokenGateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2020, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\ninterface ITokenGateway {\n /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated\n // event OutboundTransferInitiated(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized\n // event InboundTransferFinalized(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n function outboundTransfer(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n function finalizeInboundTransfer(\n address _token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n\n /**\n * @notice Calculate the address used when bridging an ERC20 token\n * @dev the L1 and L2 address oracles may not always be in sync.\n * For example, a custom token may have been registered but not deployed or the contract self destructed.\n * @param l1ERC20 address of L1 token\n * @return L2 address of a bridged ERC20 token\n */\n function calculateL2TokenAddress(address l1ERC20) external view returns (address);\n}\n" + }, + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n OwnableInitializable._initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 internal _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSelector(\n GraphTokenLockWallet.initialize.selector,\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(\n string[] calldata _signatures,\n address[] calldata _targets\n ) external override onlyOwner {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n *\n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n OwnableInitializable._initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) internal {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe because we are using the max uint256 value\n token.approve(dstList[i], type(uint256).max);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe cause we're using 0 as the amount\n token.approve(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n require(msg.value == 0, \"ETH transfers not supported\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n\n /**\n * @notice Receive function that always reverts.\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\n */\n receive() external payable {\n revert(\"Bad call\");\n }\n}\n" + }, + "contracts/ICallhookReceiver.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\n\n/**\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\n * be allowlisted by the governor, but also implement this interface that contains\n * the function that will actually be called by the L2GraphTokenGateway.\n */\npragma solidity ^0.7.3;\n\ninterface ICallhookReceiver {\n /**\n * @notice Receive tokens with a callhook from the bridge\n * @param _from Token sender in L1\n * @param _amount Amount of tokens that were transferred\n * @param _data ABI-encoded callhook data\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/L1GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { AddressUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { MinimalProxyFactory } from \"./MinimalProxyFactory.sol\";\nimport { IGraphTokenLock } from \"./IGraphTokenLock.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { SafeMathUpgradeable } from \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @title L1GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from GraphTokenLockWallets\n * to a counterpart on L2. It is deployed on L1 and will send the GRT through\n * the L1GraphTokenGateway with a callhook to the L2GraphTokenLockManager, including\n * data to create a L2GraphTokenLockWallet on L2.\n *\n * Note that the L2GraphTokenLockWallet will not allow releasing any GRT until the end of\n * the vesting timeline, but will allow sending the GRT back to the L1 wallet.\n *\n * Beneficiaries for a GraphTokenLockWallet can perform the depositToL2Locked call\n * as many times as they want, and the GRT will be sent to the same L2GraphTokenLockWallet.\n *\n * Since all retryable tickets to send transactions to L2 require ETH for gas, this\n * contract also allows users to deposit ETH to be used for gas on L2, both for\n * the depositToL2Locked calls and for the transfer tools in the Staking contract for\n * The Graph.\n *\n * See GIP-0046 for more details: https://forum.thegraph.com/t/4023\n */\ncontract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, MinimalProxyFactory {\n using SafeMathUpgradeable for uint256;\n\n /// Address of the L1 GRT token contract\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses\n address public immutable l2Implementation;\n /// Address of the L1GraphTokenGateway contract\n ITokenGateway public immutable l1Gateway;\n /// Address of the Staking contract, used to pull ETH for L2 ticket gas\n address payable public immutable staking;\n /// L2 lock manager for each L1 lock manager.\n /// L1 GraphTokenLockManager => L2GraphTokenLockManager\n mapping(address => address) public l2LockManager;\n /// L2 wallet owner for each L1 wallet owner.\n /// L1 wallet owner => L2 wallet owner\n mapping(address => address) public l2WalletOwner;\n /// L2 wallet address for each L1 wallet address.\n /// L1 wallet => L2 wallet\n mapping(address => address) public l2WalletAddress;\n /// ETH balance from each token lock, used to pay for L2 gas:\n /// L1 wallet address => ETH balance\n mapping(address => uint256) public tokenLockETHBalances;\n /// L2 beneficiary corresponding to each L1 wallet address.\n /// L1 wallet => L2 beneficiary\n mapping(address => address) public l2Beneficiary;\n /// Indicates whether an L2 wallet address for a wallet\n /// has been set manually, in which case it can't call depositToL2Locked.\n /// L1 wallet => bool\n mapping(address => bool) public l2WalletAddressSetManually;\n\n /// @dev Emitted when the L2 lock manager for an L1 lock manager is set\n event L2LockManagerSet(address indexed l1LockManager, address indexed l2LockManager);\n /// @dev Emitted when the L2 wallet owner for an L1 wallet owner is set\n event L2WalletOwnerSet(address indexed l1WalletOwner, address indexed l2WalletOwner);\n /// @dev Emitted when GRT is sent to L2 from a token lock\n event LockedFundsSentToL2(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l1LockManager,\n address l2LockManager,\n uint256 amount\n );\n /// @dev Emitted when an L2 wallet address is set for an L1 wallet\n event L2WalletAddressSet(address indexed l1Wallet, address indexed l2Wallet);\n /// @dev Emitted when ETH is deposited to a token lock's account\n event ETHDeposited(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when ETH is withdrawn from a token lock's account\n event ETHWithdrawn(address indexed tokenLock, address indexed destination, uint256 amount);\n /// @dev Emitted when ETH is pulled from a token lock's account by Staking or this tool to pay for an L2 ticket\n event ETHPulled(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when the L2 beneficiary for a partially vested L1 lock is set\n event L2BeneficiarySet(address indexed l1Wallet, address indexed l2Beneficiary);\n\n /**\n * @notice Construct a new L1GraphTokenLockTransferTool contract\n * @dev The deployer of the contract will become its owner.\n * Note this contract is meant to be deployed behind a transparent proxy,\n * so this will run at the implementation's storage context; it will set\n * immutable variables and make the implementation be owned by the deployer.\n * @param _graphToken Address of the L1 GRT token contract\n * @param _l2Implementation Address of the L2GraphTokenLockWallet implementation in L2\n * @param _l1Gateway Address of the L1GraphTokenGateway contract\n * @param _staking Address of the Staking contract\n */\n constructor(\n IERC20 _graphToken,\n address _l2Implementation,\n ITokenGateway _l1Gateway,\n address payable _staking\n ) initializer {\n OwnableInitializable._initialize(msg.sender);\n graphToken = _graphToken;\n l2Implementation = _l2Implementation;\n l1Gateway = _l1Gateway;\n staking = _staking;\n }\n\n /**\n * @notice Initialize the L1GraphTokenLockTransferTool contract\n * @dev This function will run in the proxy's storage context, so it will\n * set the owner of the proxy contract which can be different from the implementation owner.\n * @param _owner Address of the owner of the L1GraphTokenLockTransferTool contract\n */\n function initialize(address _owner) external initializer {\n OwnableInitializable._initialize(_owner);\n }\n\n /**\n * @notice Set the L2 lock manager that corresponds to an L1 lock manager\n * @param _l1LockManager Address of the L1 lock manager\n * @param _l2LockManager Address of the L2 lock manager (in L2)\n */\n function setL2LockManager(address _l1LockManager, address _l2LockManager) external onlyOwner {\n l2LockManager[_l1LockManager] = _l2LockManager;\n emit L2LockManagerSet(_l1LockManager, _l2LockManager);\n }\n\n /**\n * @notice Set the L2 wallet owner that corresponds to an L1 wallet owner\n * @param _l1WalletOwner Address of the L1 wallet owner\n * @param _l2WalletOwner Address of the L2 wallet owner (in L2)\n */\n function setL2WalletOwner(address _l1WalletOwner, address _l2WalletOwner) external onlyOwner {\n l2WalletOwner[_l1WalletOwner] = _l2WalletOwner;\n emit L2WalletOwnerSet(_l1WalletOwner, _l2WalletOwner);\n }\n\n /**\n * @notice Deposit ETH on a token lock's account, to be used for L2 retryable ticket gas.\n * This function can be called by anyone, but the ETH will be credited to the token lock.\n * DO NOT try to call this through the token lock, as locks do not forward ETH value (and the\n * function call should not be allowlisted).\n * @param _tokenLock Address of the L1 GraphTokenLockWallet that will own the ETH\n */\n function depositETH(address _tokenLock) external payable {\n tokenLockETHBalances[_tokenLock] = tokenLockETHBalances[_tokenLock].add(msg.value);\n emit ETHDeposited(_tokenLock, msg.value);\n }\n\n /**\n * @notice Withdraw ETH from a token lock's account.\n * This function must be called from the token lock contract, but the destination\n * _must_ be a different address, as any ETH sent to the token lock would otherwise be\n * lost.\n * @param _destination Address to send the ETH\n * @param _amount Amount of ETH to send\n */\n function withdrawETH(address _destination, uint256 _amount) external {\n require(_amount > 0, \"INVALID_AMOUNT\");\n // We can't send eth to a token lock or it will be stuck\n require(msg.sender != _destination, \"INVALID_DESTINATION\");\n require(tokenLockETHBalances[msg.sender] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[msg.sender] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = payable(_destination).call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHWithdrawn(msg.sender, _destination, _amount);\n }\n\n /**\n * @notice Pull ETH from a token lock's account, to be used for L2 retryable ticket gas.\n * This can only be called by the Staking contract.\n * @param _tokenLock GraphTokenLockWallet that owns the ETH that will be debited\n * @param _amount Amount of ETH to pull\n */\n function pullETH(address _tokenLock, uint256 _amount) external {\n require(msg.sender == staking, \"ONLY_STAKING\");\n require(tokenLockETHBalances[_tokenLock] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[_tokenLock] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = staking.call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHPulled(_tokenLock, _amount);\n }\n\n /**\n * @notice Deposit GRT to L2, from a token lock in L1 to a token lock in L2.\n * If the token lock in L2 does not exist, it will be created when the message is received\n * by the L2GraphTokenLockManager.\n * Before calling this (which must be done through the token lock wallet), make sure\n * there is enough ETH in the token lock's account to cover the L2 retryable ticket gas.\n * Note that L2 submission fee and gas refunds will be lost.\n * You can add ETH to the token lock's account by calling depositETH().\n * Note that after calling this, you will NOT be able to use setL2WalletAddressManually() to\n * set an L2 wallet address, as the L2 wallet address will be set automatically when the\n * message is received by the L2GraphTokenLockManager.\n * @dev The gas parameters for L2 can be estimated using the Arbitrum SDK.\n * @param _amount Amount of GRT to deposit\n * @param _l2Beneficiary Address of the beneficiary for the token lock in L2. Must be the same for subsequent calls of this function, and not an L1 contract.\n * @param _maxGas Maximum gas to use for the L2 retryable ticket\n * @param _gasPriceBid Gas price to use for the L2 retryable ticket\n * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket\n */\n function depositToL2Locked(\n uint256 _amount,\n address _l2Beneficiary,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n uint256 _maxSubmissionCost\n ) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n require(wallet.revocable() != IGraphTokenLock.Revocability.Enabled, \"REVOCABLE\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n if (l2Beneficiary[msg.sender] == address(0)) {\n require(_l2Beneficiary != address(0), \"INVALID_BENEFICIARY_ZERO\");\n require(!AddressUpgradeable.isContract(_l2Beneficiary), \"INVALID_BENEFICIARY_CONTRACT\");\n l2Beneficiary[msg.sender] = _l2Beneficiary;\n emit L2BeneficiarySet(msg.sender, _l2Beneficiary);\n } else {\n require(l2Beneficiary[msg.sender] == _l2Beneficiary, \"INVALID_BENEFICIARY\");\n }\n\n uint256 expectedEth = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(tokenLockETHBalances[msg.sender] >= expectedEth, \"INSUFFICIENT_ETH_BALANCE\");\n tokenLockETHBalances[msg.sender] -= expectedEth;\n\n bytes memory encodedData;\n {\n address l2Owner = l2WalletOwner[wallet.owner()];\n require(l2Owner != address(0), \"L2_OWNER_NOT_SET\");\n // Extract all the storage variables from the GraphTokenLockWallet\n L2GraphTokenLockManager.TransferredWalletData memory data = L2GraphTokenLockManager.TransferredWalletData({\n l1Address: msg.sender,\n owner: l2Owner,\n beneficiary: l2Beneficiary[msg.sender],\n managedAmount: wallet.managedAmount(),\n startTime: wallet.startTime(),\n endTime: wallet.endTime()\n });\n encodedData = abi.encode(data);\n }\n\n if (l2WalletAddress[msg.sender] == address(0)) {\n require(wallet.endTime() >= block.timestamp, \"FULLY_VESTED_USE_MANUAL_ADDRESS\");\n address newAddress = getDeploymentAddress(keccak256(encodedData), l2Implementation, l2Manager);\n l2WalletAddress[msg.sender] = newAddress;\n emit L2WalletAddressSet(msg.sender, newAddress);\n } else {\n require(!l2WalletAddressSetManually[msg.sender], \"CANT_DEPOSIT_TO_MANUAL_ADDRESS\");\n }\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n\n // Send the tokens with a message through the L1GraphTokenGateway to the L2GraphTokenLockManager\n graphToken.approve(address(l1Gateway), _amount);\n {\n bytes memory transferData = abi.encode(_maxSubmissionCost, encodedData);\n l1Gateway.outboundTransfer{ value: expectedEth }(\n address(graphToken),\n l2Manager,\n _amount,\n _maxGas,\n _gasPriceBid,\n transferData\n );\n }\n emit ETHPulled(msg.sender, expectedEth);\n emit LockedFundsSentToL2(msg.sender, l2WalletAddress[msg.sender], l1Manager, l2Manager, _amount);\n }\n\n /**\n * @notice Manually set the L2 wallet address for a token lock in L1.\n * This will only work for token locks that have not been initialized in L2 yet, and\n * that are fully vested (endTime < current timestamp).\n * This address can then be used to send stake or delegation to L2 on the Staking contract.\n * After calling this, the vesting lock will NOT be allowed to use depositToL2Locked\n * to send GRT to L2, the beneficiary must withdraw the tokens and bridge them manually.\n * @param _l2Wallet Address of the L2 wallet\n */\n function setL2WalletAddressManually(address _l2Wallet) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n\n // Check that the wallet is fully vested\n require(wallet.endTime() < block.timestamp, \"NOT_FULLY_VESTED\");\n\n // Check that the wallet has not set an L2 wallet yet\n require(l2WalletAddress[msg.sender] == address(0), \"L2_WALLET_ALREADY_SET\");\n\n // Check that the L2 address is not zero\n require(_l2Wallet != address(0), \"ZERO_ADDRESS\");\n // Set the L2 wallet address\n l2WalletAddress[msg.sender] = _l2Wallet;\n l2WalletAddressSetManually[msg.sender] = true;\n emit L2WalletAddressSet(msg.sender, _l2Wallet);\n }\n}\n" + }, + "contracts/L2GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { ICallhookReceiver } from \"./ICallhookReceiver.sol\";\nimport { GraphTokenLockManager } from \"./GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\n\n/**\n * @title L2GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\n * the L2GraphTokenLockTransferTool contract.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\n using SafeERC20 for IERC20;\n\n /// @dev Struct to hold the data of a transferred wallet; this is\n /// the data that must be encoded in L1 to send a wallet to L2.\n struct TransferredWalletData {\n address l1Address;\n address owner;\n address beneficiary;\n uint256 managedAmount;\n uint256 startTime;\n uint256 endTime;\n }\n\n /// Address of the L2GraphTokenGateway\n address public immutable l2Gateway;\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\n address public immutable l1TransferTool;\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\n /// L1 address => L2 address\n mapping(address => address) public l1WalletToL2Wallet;\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\n /// L2 address => L1 address\n mapping(address => address) public l2WalletToL1Wallet;\n\n /// @dev Event emitted when a wallet is received and created from L1\n event TokenLockCreatedFromL1(\n address indexed contractAddress,\n bytes32 initHash,\n address indexed beneficiary,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n address indexed l1Address\n );\n\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\n /// had already been received or not)\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\n\n /**\n * @dev Checks that the sender is the L2GraphTokenGateway.\n */\n modifier onlyL2Gateway() {\n require(msg.sender == l2Gateway, \"ONLY_GATEWAY\");\n _;\n }\n\n /**\n * @notice Constructor for the L2GraphTokenLockManager contract.\n * @param _graphToken Address of the L2 GRT token contract\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\n */\n constructor(\n IERC20 _graphToken,\n address _masterCopy,\n address _l2Gateway,\n address _l1TransferTool\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\n l2Gateway = _l2Gateway;\n l1TransferTool = _l1TransferTool;\n }\n\n /**\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\n * the existing wallet if it does.\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\n * @param _amount Amount of tokens received\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\n require(_from == l1TransferTool, \"ONLY_TRANSFER_TOOL\");\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\n\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\n // If the wallet was already received, just send the tokens to the L2 address\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\n } else {\n // Create contract using a minimal proxy and call initializer\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _amount);\n\n emit TokenLockCreatedFromL1(\n contractAddress,\n initHash,\n walletData.beneficiary,\n walletData.managedAmount,\n walletData.startTime,\n walletData.endTime,\n walletData.l1Address\n );\n }\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\n }\n\n /**\n * @dev Deploy a token lock wallet with data received from L1\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\n * @param _walletData Data of the wallet to be created\n * @return Hash of the initialization calldata\n * @return Address of the created contract\n */\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\n bytes memory initializer = _encodeInitializer(_walletData);\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\n return (keccak256(initializer), contractAddress);\n }\n\n /**\n * @dev Encode the initializer for the token lock wallet received from L1\n * @param _walletData Data of the wallet to be created\n * @return Encoded initializer calldata, including the function signature\n */\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\n return\n abi.encodeWithSelector(\n L2GraphTokenLockWallet.initializeFromL1.selector,\n address(this),\n address(_token),\n _walletData\n );\n }\n}\n" + }, + "contracts/L2GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\n\n/**\n * @title L2GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from L2 token lock wallets\n * back to their L1 counterparts.\n */\ncontract L2GraphTokenLockTransferTool {\n /// Address of the L2 GRT token\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenGateway\n ITokenGateway public immutable l2Gateway;\n /// Address of the L1 GRT token (in L1, no aliasing)\n address public immutable l1GraphToken;\n\n /// @dev Emitted when GRT is sent to L1 from a token lock\n event LockedFundsSentToL1(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l2LockManager,\n uint256 amount\n );\n\n /**\n * @notice Constructor for the L2GraphTokenLockTransferTool contract\n * @dev Note the L2GraphTokenLockTransferTool can be deployed behind a proxy,\n * and the constructor for the implementation will only set some immutable\n * variables.\n * @param _graphToken Address of the L2 GRT token\n * @param _l2Gateway Address of the L2GraphTokenGateway\n * @param _l1GraphToken Address of the L1 GRT token (in L1, no aliasing)\n */\n constructor(IERC20 _graphToken, ITokenGateway _l2Gateway, address _l1GraphToken) {\n graphToken = _graphToken;\n l2Gateway = _l2Gateway;\n l1GraphToken = _l1GraphToken;\n }\n\n /**\n * @notice Withdraw GRT from an L2 token lock wallet to its L1 counterpart.\n * This function must be called from an L2GraphTokenLockWallet contract.\n * The GRT will be sent to L1 and must be claimed using the Arbitrum Outbox on L1\n * after the standard Arbitrum withdrawal period (7 days).\n * @param _amount Amount of GRT to withdraw\n */\n function withdrawToL1Locked(uint256 _amount) external {\n L2GraphTokenLockWallet wallet = L2GraphTokenLockWallet(msg.sender);\n L2GraphTokenLockManager manager = L2GraphTokenLockManager(address(wallet.manager()));\n require(address(manager) != address(0), \"INVALID_SENDER\");\n address l1Wallet = manager.l2WalletToL1Wallet(msg.sender);\n require(l1Wallet != address(0), \"NOT_L1_WALLET\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n graphToken.approve(address(l2Gateway), _amount);\n\n // Send the tokens through the L2GraphTokenGateway to the L1 wallet counterpart\n l2Gateway.outboundTransfer(l1GraphToken, l1Wallet, _amount, 0, 0, \"\");\n emit LockedFundsSentToL1(l1Wallet, msg.sender, address(manager), _amount);\n }\n}\n" + }, + "contracts/L2GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\n\n/**\n * @title L2GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * This L2 variant includes a special initializer so that it can be created from\n * a wallet's data received from L1. These transferred wallets will not allow releasing\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\n *\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\n // Initializer when created from a message from L1\n function initializeFromL1(\n address _manager,\n address _token,\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\n ) external {\n require(!isInitialized, \"Already initialized\");\n isInitialized = true;\n\n OwnableInitializable._initialize(_walletData.owner);\n beneficiary = _walletData.beneficiary;\n token = IERC20(_token);\n\n managedAmount = _walletData.managedAmount;\n\n startTime = _walletData.startTime;\n endTime = _walletData.endTime;\n periods = 1;\n isAccepted = true;\n\n // Optionals\n releaseStartTime = _walletData.endTime;\n revocable = Revocability.Disabled;\n\n _setManager(_manager);\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { Create2 } from \"@openzeppelin/contracts/utils/Create2.sol\";\n\n/**\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n * Based on https://eips.ethereum.org/EIPS/eip-1167\n */\ncontract MinimalProxyFactory {\n /// @dev Emitted when a new proxy is created\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _deployer Address of the deployer that creates the contract\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation,\n address _deployer\n ) public pure returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\n }\n\n /**\n * @dev Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @dev Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n /// @dev Owner of the contract, can be retrieved with the public owner() function\n address private _owner;\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\n /// to allow adding variables here without breaking the proxy storage layout\n uint256[50] private __gap;\n\n /// @dev Emitted when ownership of the contract is transferred\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function _initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/tests/arbitrum/AddressAliasHelper.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/84e64dee6ee82adbf8ec34fd4b86c207a61d9007/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n l2Address = address(uint160(l1Address) + offset);\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n l1Address = address(uint160(l2Address) - offset);\n }\n}\n" + }, + "contracts/tests/arbitrum/IBridge.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IBridge {\n event MessageDelivered(\n uint256 indexed messageIndex,\n bytes32 indexed beforeInboxAcc,\n address inbox,\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n );\n\n event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);\n\n event InboxToggle(address indexed inbox, bool enabled);\n\n event OutboxToggle(address indexed outbox, bool enabled);\n\n function deliverMessageToInbox(\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n ) external payable returns (uint256);\n\n function executeCall(\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (bool success, bytes memory returnData);\n\n // These are only callable by the admin\n function setInbox(address inbox, bool enabled) external;\n\n function setOutbox(address inbox, bool enabled) external;\n\n // View functions\n\n function activeOutbox() external view returns (address);\n\n function allowedInboxes(address inbox) external view returns (bool);\n\n function allowedOutboxes(address outbox) external view returns (bool);\n\n function inboxAccs(uint256 index) external view returns (bytes32);\n\n function messageCount() external view returns (uint256);\n}\n" + }, + "contracts/tests/arbitrum/IInbox.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nimport \"./IBridge.sol\";\nimport \"./IMessageProvider.sol\";\n\ninterface IInbox is IMessageProvider {\n function sendL2Message(bytes calldata messageData) external returns (uint256);\n\n function sendUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendL1FundedUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function sendL1FundedContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function createRetryableTicket(\n address destAddr,\n uint256 arbTxCallValue,\n uint256 maxSubmissionCost,\n address submissionRefundAddress,\n address valueRefundAddress,\n uint256 maxGas,\n uint256 gasPriceBid,\n bytes calldata data\n ) external payable returns (uint256);\n\n function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);\n\n function bridge() external view returns (IBridge);\n\n function pauseCreateRetryables() external;\n\n function unpauseCreateRetryables() external;\n\n function startRewriteAddress() external;\n\n function stopRewriteAddress() external;\n}\n" + }, + "contracts/tests/arbitrum/IMessageProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IMessageProvider {\n event InboxMessageDelivered(uint256 indexed messageNum, bytes data);\n\n event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);\n}\n" + }, + "contracts/tests/BridgeMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IBridge.sol\";\n\n/**\n * @title Arbitrum Bridge mock contract\n * @dev This contract implements Arbitrum's IBridge interface for testing purposes\n */\ncontract BridgeMock is IBridge {\n /// Address of the (mock) Arbitrum Inbox\n address public inbox;\n /// Address of the (mock) Arbitrum Outbox\n address public outbox;\n /// Index of the next message on the inbox messages array\n uint256 public messageIndex;\n /// Inbox messages array\n bytes32[] public override inboxAccs;\n\n /**\n * @notice Deliver a message to the inbox. The encoded message will be\n * added to the inbox array, and messageIndex will be incremented.\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the message data\n * @return The next index for the inbox array\n */\n function deliverMessageToInbox(\n uint8 _kind,\n address _sender,\n bytes32 _messageDataHash\n ) external payable override returns (uint256) {\n messageIndex = messageIndex + 1;\n inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash)));\n emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash);\n return messageIndex;\n }\n\n /**\n * @notice Executes an L1 function call incoing from L2. This can only be called\n * by the Outbox.\n * @param _destAddr Contract to call\n * @param _amount ETH value to send\n * @param _data Calldata for the function call\n * @return True if the call was successful, false otherwise\n * @return Return data from the call\n */\n function executeCall(\n address _destAddr,\n uint256 _amount,\n bytes calldata _data\n ) external override returns (bool, bytes memory) {\n require(outbox == msg.sender, \"NOT_FROM_OUTBOX\");\n bool success;\n bytes memory returnData;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, returnData) = _destAddr.call{ value: _amount }(_data);\n emit BridgeCallTriggered(msg.sender, _destAddr, _amount, _data);\n return (success, returnData);\n }\n\n /**\n * @notice Set the address of the inbox. Anyone can call this, because it's a mock.\n * @param _inbox Address of the inbox\n * @param _enabled Enable the inbox (ignored)\n */\n function setInbox(address _inbox, bool _enabled) external override {\n inbox = _inbox;\n emit InboxToggle(inbox, _enabled);\n }\n\n /**\n * @notice Set the address of the outbox. Anyone can call this, because it's a mock.\n * @param _outbox Address of the outbox\n * @param _enabled Enable the outbox (ignored)\n */\n function setOutbox(address _outbox, bool _enabled) external override {\n outbox = _outbox;\n emit OutboxToggle(outbox, _enabled);\n }\n\n // View functions\n\n /**\n * @notice Getter for the active outbox (in this case there's only one)\n */\n function activeOutbox() external view override returns (address) {\n return outbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed inbox (in this case there's only one)\n * @param _inbox Address to check\n * @return True if the address is the allowed inbox, false otherwise\n */\n function allowedInboxes(address _inbox) external view override returns (bool) {\n return _inbox == inbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed outbox (in this case there's only one)\n * @param _outbox Address to check\n * @return True if the address is the allowed outbox, false otherwise\n */\n function allowedOutboxes(address _outbox) external view override returns (bool) {\n return _outbox == outbox;\n }\n\n /**\n * @notice Getter for the count of messages in the inboxAccs\n * @return Number of messages in inboxAccs\n */\n function messageCount() external view override returns (uint256) {\n return inboxAccs.length;\n }\n}\n" + }, + "contracts/tests/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock contract.\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @notice Contract Constructor.\n * @param _initialSupply Initial supply\n * @param _mintTo Address to whitch to mint the initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n\n /**\n * @notice Mint tokens to an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _to Address to mint tokens to\n * @param _amount Amount of tokens to mint\n */\n function bridgeMint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n\n /**\n * @notice Burn tokens from an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _from Address to burn tokens from\n * @param _amount Amount of tokens to burn\n */\n function bridgeBurn(address _from, uint256 _amount) external {\n _burn(_from, _amount);\n }\n}\n" + }, + "contracts/tests/InboxMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IInbox.sol\";\nimport \"./arbitrum/AddressAliasHelper.sol\";\n\n/**\n * @title Arbitrum Inbox mock contract\n * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes\n */\ncontract InboxMock is IInbox {\n /// @dev Type indicator for a standard L2 message\n uint8 internal constant L2_MSG = 3;\n /// @dev Type indicator for a retryable ticket message\n // solhint-disable-next-line const-name-snakecase\n uint8 internal constant L1MessageType_submitRetryableTx = 9;\n /// Address of the Bridge (mock) contract\n IBridge public override bridge;\n\n /**\n * @notice Send a message to L2 (by delivering it to the Bridge)\n * @param _messageData Encoded data to send in the message\n * @return Message number returned by the inbox\n */\n function sendL2Message(bytes calldata _messageData) external override returns (uint256) {\n uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @notice Set the address of the (mock) bridge\n * @param _bridge Address of the bridge\n */\n function setBridge(address _bridge) external {\n bridge = IBridge(_bridge);\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendContractTransaction(\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedContractTransaction(\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Creates a retryable ticket for an L2 transaction\n * @param _destAddr Address of the contract to call in L2\n * @param _arbTxCallValue Callvalue to use in the L2 transaction\n * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei\n * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost\n * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled\n * @param _maxGas Max gas for the L2 transcation\n * @param _gasPriceBid Gas price bid on L2\n * @param _data Encoded calldata for the L2 transaction (including function selector)\n * @return Message number returned by the bridge\n */\n function createRetryableTicket(\n address _destAddr,\n uint256 _arbTxCallValue,\n uint256 _maxSubmissionCost,\n address _submissionRefundAddress,\n address _valueRefundAddress,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable override returns (uint256) {\n _submissionRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_submissionRefundAddress);\n _valueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_valueRefundAddress);\n return\n _deliverMessage(\n L1MessageType_submitRetryableTx,\n msg.sender,\n abi.encodePacked(\n uint256(uint160(bytes20(_destAddr))),\n _arbTxCallValue,\n msg.value,\n _maxSubmissionCost,\n uint256(uint160(bytes20(_submissionRefundAddress))),\n uint256(uint160(bytes20(_valueRefundAddress))),\n _maxGas,\n _gasPriceBid,\n _data.length,\n _data\n )\n );\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function depositEth(uint256) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function pauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function unpauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function startRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function stopRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageData Encoded message data\n * @return Message number returned by the bridge\n */\n function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) {\n uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the encoded message data\n * @return Message number returned by the bridge\n */\n function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) {\n return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash);\n }\n}\n" + }, + "contracts/tests/L1TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\n\n/**\n * @title L1 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L1TokenGatewayMock is Ownable {\n using SafeMath for uint256;\n /// Next sequence number to return when outboundTransfer is called\n uint256 public nextSeqNum;\n\n /// @dev Emitted when a (fake) retryable ticket is created\n event FakeTxToL2(\n address from,\n uint256 value,\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 maxSubmissionCost,\n bytes outboundCalldata\n );\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2\n event DepositInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L1 Token Gateway Contract Constructor.\n */\n constructor() {}\n\n /**\n * @notice Creates and sends a fake retryable ticket to transfer GRT to L2.\n * This mock will actually just emit an event with parameters equivalent to what the real L1GraphTokenGateway\n * would send to L2.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _maxGas Gas limit for L2 execution of the ticket\n * @param _gasPriceBid Price per gas on L2\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return Sequence number of the retryable ticket created by Inbox (always )\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 seqNum = nextSeqNum;\n nextSeqNum += 1;\n {\n uint256 maxSubmissionCost;\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, maxSubmissionCost, extraData) = _parseOutboundData(_data);\n require(maxSubmissionCost > 0, \"NO_SUBMISSION_COST\");\n\n {\n // makes sure only sufficient ETH is supplied as required for successful redemption on L2\n // if a user does not desire immediate redemption they should provide\n // a msg.value of AT LEAST maxSubmissionCost\n uint256 expectedEth = maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(msg.value >= expectedEth, \"WRONG_ETH_VALUE\");\n }\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // transfer tokens to escrow\n IERC20(_l1Token).transferFrom(from, address(this), _amount);\n\n emit FakeTxToL2(from, msg.value, _maxGas, _gasPriceBid, maxSubmissionCost, outboundCalldata);\n }\n }\n emit DepositInitiated(_l1Token, from, _to, seqNum, _amount);\n\n return abi.encode(seqNum);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L2\n * Actually does nothing, just keeping it here as its useful to define the expected\n * calldata for the outgoing transfer in tests.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recepient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {}\n\n /**\n * @notice Creates calldata required to create a retryable ticket\n * @dev encodes the target function with its params which\n * will be called on L2 when the retryable ticket is redeemed\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L1 from which we're transferring tokens\n * @param _to Address on L2 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L2 transaction, which must be empty unless the caller is whitelisted\n * @return Encoded calldata (including function selector) for the L2 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n bytes memory emptyBytes;\n\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(emptyBytes, _data)\n );\n }\n\n /**\n * @notice Decodes calldata required for transfer of tokens to L2\n * @dev Data must include maxSubmissionCost, extraData can be left empty. When the router\n * sends an outbound message, data also contains the from address, but this mock\n * doesn't consider this case\n * @param _data Encoded callhook data containing maxSubmissionCost and extraData\n * @return Sender of the tx\n * @return Max ether value used to submit the retryable ticket\n * @return Additional data sent to L2\n */\n function _parseOutboundData(bytes memory _data) private view returns (address, uint256, bytes memory) {\n address from;\n uint256 maxSubmissionCost;\n bytes memory extraData;\n from = msg.sender;\n // User-encoded data contains the max retryable ticket submission cost\n // and additional L2 calldata\n (maxSubmissionCost, extraData) = abi.decode(_data, (uint256, bytes));\n return (from, maxSubmissionCost, extraData);\n }\n}\n" + }, + "contracts/tests/L2TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\nimport { GraphTokenMock } from \"./GraphTokenMock.sol\";\nimport { ICallhookReceiver } from \"../ICallhookReceiver.sol\";\n\n/**\n * @title L2 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L2TokenGatewayMock is Ownable {\n /// Address of the L1 GRT contract\n address public immutable l1Token;\n /// Address of the L2 GRT contract\n address public immutable l2Token;\n /// Next ID to return when sending an outboundTransfer\n uint256 public nextId;\n\n /// @dev Emitted when a (fake) transaction to L1 is created\n event FakeTxToL1(address from, bytes outboundCalldata);\n /// @dev Emitted when a (fake) retryable ticket is received from L1\n event DepositFinalized(address token, address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are withdrawn to L1 from L2\n event WithdrawalInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L2 Token Gateway Contract Constructor.\n * @param _l1Token Address of the L1 GRT contract\n * @param _l2Token Address of the L2 GRT contract\n */\n constructor(address _l1Token, address _l2Token) {\n l1Token = _l1Token;\n l2Token = _l2Token;\n }\n\n /**\n * @notice Creates and sends a (fake) transfer of GRT to L1.\n * This mock will actually just emit an event with parameters equivalent to what the real L2GraphTokenGateway\n * would send to L1.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return ID of the L2-L1 message (incrementing on every call)\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_l1Token == l1Token, \"INVALID_L1_TOKEN\");\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 id = nextId;\n nextId += 1;\n {\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, extraData) = _parseOutboundData(_data);\n\n require(msg.value == 0, \"!value\");\n require(extraData.length == 0, \"!extraData\");\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // burn tokens from the sender, they will be released from escrow in L1\n GraphTokenMock(l2Token).bridgeBurn(from, _amount);\n\n emit FakeTxToL1(from, outboundCalldata);\n }\n }\n emit WithdrawalInitiated(_l1Token, from, _to, id, _amount);\n\n return abi.encode(id);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L1\n * Implements calling callhooks if data is non-empty.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recipient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata, will trigger an onTokenTransfer call if non-empty\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {\n require(_l1Token == l1Token, \"TOKEN_NOT_GRT\");\n require(msg.value == 0, \"INVALID_NONZERO_VALUE\");\n\n GraphTokenMock(l2Token).bridgeMint(_to, _amount);\n\n if (_data.length > 0) {\n ICallhookReceiver(_to).onTokenTransfer(_from, _amount, _data);\n }\n\n emit DepositFinalized(_l1Token, _from, _to, _amount);\n }\n\n /**\n * @notice Calculate the L2 address of a bridged token\n * @dev In our case, this would only work for GRT.\n * @param l1ERC20 address of L1 GRT contract\n * @return L2 address of the bridged GRT token\n */\n function calculateL2TokenAddress(address l1ERC20) public view returns (address) {\n if (l1ERC20 != l1Token) {\n return address(0);\n }\n return l2Token;\n }\n\n /**\n * @notice Creates calldata required to create a tx to L1\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L2 from which we're transferring tokens\n * @param _to Address on L1 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L1 transaction, which must be empty\n * @return Encoded calldata (including function selector) for the L1 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(0, _data)\n );\n }\n\n /**\n * @dev Decodes calldata required for transfer of tokens to L1.\n * extraData can be left empty\n * @param _data Encoded callhook data\n * @return Sender of the tx\n * @return Any other data sent to L1\n */\n function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {\n address from;\n bytes memory extraData;\n // The mock doesn't take messages from the Router\n from = msg.sender;\n extraData = _data;\n return (from, extraData);\n }\n}\n" + }, + "contracts/tests/Stakes.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(\n Stakes.Indexer memory stake,\n uint256 _delegatedCapacity\n ) internal pure returns (uint256) {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "contracts/tests/StakingMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n receive() external payable {}\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/tests/WalletMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title WalletMock: a mock wallet contract for testing purposes\n * @dev For testing only, DO NOT USE IN PRODUCTION.\n * This is used to test L1-L2 transfer tools and to create scenarios\n * where an invalid wallet calls the transfer tool, e.g. a wallet that has an invalid\n * manager, or a wallet that has not been initialized.\n */\ncontract WalletMock {\n /// Target contract for the fallback function (usually a transfer tool contract)\n address public immutable target;\n /// Address of the GRT (mock) token\n address public immutable token;\n /// Address of the wallet's manager\n address public immutable manager;\n /// Whether the wallet has been initialized\n bool public immutable isInitialized;\n /// Whether the beneficiary has accepted the lock\n bool public immutable isAccepted;\n\n /**\n * @notice WalletMock constructor\n * @dev This constructor sets all the state variables so that\n * specific test scenarios can be created just by deploying this contract.\n * @param _target Target contract for the fallback function\n * @param _token Address of the GRT (mock) token\n * @param _manager Address of the wallet's manager\n * @param _isInitialized Whether the wallet has been initialized\n * @param _isAccepted Whether the beneficiary has accepted the lock\n */\n constructor(address _target, address _token, address _manager, bool _isInitialized, bool _isAccepted) {\n target = _target;\n token = _token;\n manager = _manager;\n isInitialized = _isInitialized;\n isAccepted = _isAccepted;\n }\n\n /**\n * @notice Fallback function\n * @dev This function calls the target contract with the data sent to this contract.\n * This is used to test the L1-L2 transfer tool.\n */\n fallback() external payable {\n // Call function with data\n Address.functionCall(target, msg.data);\n }\n\n /**\n * @notice Receive function\n * @dev This function is added to avoid compiler warnings, but just reverts.\n */\n receive() external payable {\n revert(\"Invalid call\");\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/.chainId b/packages/token-distribution/deployments/mainnet/.chainId new file mode 100644 index 000000000..56a6051ca --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/.chainId @@ -0,0 +1 @@ +1 \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Foundation.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Foundation.json new file mode 100644 index 000000000..3f7e0e43a --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Foundation.json @@ -0,0 +1,926 @@ +{ + "address": "0x455466E99033D1D33D6fA6EcA40F182e0A551847", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x32d3db48be816776850bd2d4d2e64351cae31fca85e9118ea90dc6eb342593c1", + "receipt": { + "to": null, + "from": "0xE04FcE05E9B8d21521bd1B0f069982c03BD31F76", + "contractAddress": "0x455466E99033D1D33D6fA6EcA40F182e0A551847", + "transactionIndex": 82, + "gasUsed": "3166292", + "logsBloom": "0x00000000000000000000400000000000000004000000000000800000000000400042000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000001000000000000000000400000000000000000020000000000000000000800000000000000000000000000000000400002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000008000000000000000000000000000000000000000000000020000020000008000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9523656a047822adc4d8c77b9a69035e06d05c8d7797ce4305cb36c1d8aa0bbd", + "transactionHash": "0x32d3db48be816776850bd2d4d2e64351cae31fca85e9118ea90dc6eb342593c1", + "logs": [ + { + "transactionIndex": 82, + "blockNumber": 15877688, + "transactionHash": "0x32d3db48be816776850bd2d4d2e64351cae31fca85e9118ea90dc6eb342593c1", + "address": "0x455466E99033D1D33D6fA6EcA40F182e0A551847", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e04fce05e9b8d21521bd1b0f069982c03bd31f76" + ], + "data": "0x", + "logIndex": 170, + "blockHash": "0x9523656a047822adc4d8c77b9a69035e06d05c8d7797ce4305cb36c1d8aa0bbd" + }, + { + "transactionIndex": 82, + "blockNumber": 15877688, + "transactionHash": "0x32d3db48be816776850bd2d4d2e64351cae31fca85e9118ea90dc6eb342593c1", + "address": "0x455466E99033D1D33D6fA6EcA40F182e0A551847", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x000000000000000000000000624984fd288e28c0d24d7e0e4adfda130717720b" + ], + "data": "0x", + "logIndex": 171, + "blockHash": "0x9523656a047822adc4d8c77b9a69035e06d05c8d7797ce4305cb36c1d8aa0bbd" + } + ], + "blockNumber": 15877688, + "cumulativeGasUsed": "9035991", + "status": 1, + "byzantium": true + }, + "args": [ + "0xc944E90C64B2c07662A292be6244BDf05Cda44a7", + "0x624984fd288e28C0D24d7E0E4aDFDa130717720B" + ], + "solcInputHash": "6f5e8f450f52dd96ebb796aa6620fee9", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address)\":{\"params\":{\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 private _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSignature(\\n \\\"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\\\",\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\\n external\\n override\\n onlyOwner\\n {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solium-disable-next-line security/no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x0384d62cb600eb4128baacf5bca60ea2cb0b68d2d013479daef65ed5f15446ef\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n// Based on https://eips.ethereum.org/EIPS/eip-1167\\ncontract MinimalProxyFactory is Ownable {\\n // -- Events --\\n\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\\n }\\n\\n /**\\n * @notice Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(\\n bytes32 _salt,\\n address _implementation,\\n bytes memory _data\\n ) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @notice Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x8aa3d50e714f92dc0ed6cc6d88fa8a18c948493103928f6092f98815b2c046ca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003c9338038062003c9383398181016040528101906200003791906200039c565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004e7565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b505062000596565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001f26200034560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200024b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024290620004c5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b590620004a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000815190506200037f8162000562565b92915050565b60008151905062000396816200057c565b92915050565b60008060408385031215620003b057600080fd5b6000620003c08582860162000385565b9250506020620003d3858286016200036e565b9150509250929050565b6000620003ec60198362000509565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006200042e60208362000509565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200047060148362000509565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004be81620003dd565b9050919050565b60006020820190508181036000830152620004e0816200041f565b9050919050565b60006020820190508181036000830152620005028162000461565b9050919050565b600082825260208201905092915050565b6000620005278262000542565b9050919050565b60006200053b826200051a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200056d816200051a565b81146200057957600080fd5b50565b62000587816200052e565b81146200059357600080fd5b50565b6136ed80620005a66000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address)": { + "params": { + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3316, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3318, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)1964_storage" + }, + { + "astId": 3320, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3322, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1045" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1045": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)1964_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 1963, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)1699_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)1699_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 1694, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 1698, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-MIPs.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-MIPs.json new file mode 100644 index 000000000..65386d2ee --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-MIPs.json @@ -0,0 +1,932 @@ +{ + "address": "0xDC55A8e2c592ced19D9Fd0f9f1083D4FD5a48031", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xa64e2e41c754b1098137b367ff1c83bf7b0de0d632d194ae82132b5b1fcc0a83", + "receipt": { + "to": null, + "from": "0x8e623680d81372926a5878f544ceFE30B35BD9a0", + "contractAddress": "0xDC55A8e2c592ced19D9Fd0f9f1083D4FD5a48031", + "transactionIndex": 10, + "gasUsed": "3166762", + "logsBloom": "0x00000000000000000000000000000000000004000000000000800000000000000000000000000000001000000000000000000000100000000000000000000000000000000000000000000002000000000001000000000000010000400000000000000040020000000000000000000800000000000000000000000000000000400000000000800000040000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1803dacb914fcad724814b7ca2a85d08c6b6d389ea6dd9b0efc8777cea154379", + "transactionHash": "0xa64e2e41c754b1098137b367ff1c83bf7b0de0d632d194ae82132b5b1fcc0a83", + "logs": [ + { + "transactionIndex": 10, + "blockNumber": 17743222, + "transactionHash": "0xa64e2e41c754b1098137b367ff1c83bf7b0de0d632d194ae82132b5b1fcc0a83", + "address": "0xDC55A8e2c592ced19D9Fd0f9f1083D4FD5a48031", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000008e623680d81372926a5878f544cefe30b35bd9a0" + ], + "data": "0x", + "logIndex": 62, + "blockHash": "0x1803dacb914fcad724814b7ca2a85d08c6b6d389ea6dd9b0efc8777cea154379" + }, + { + "transactionIndex": 10, + "blockNumber": 17743222, + "transactionHash": "0xa64e2e41c754b1098137b367ff1c83bf7b0de0d632d194ae82132b5b1fcc0a83", + "address": "0xDC55A8e2c592ced19D9Fd0f9f1083D4FD5a48031", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x0000000000000000000000001231a8579ca4208f8ae6fecc6c96bf935b73487d" + ], + "data": "0x", + "logIndex": 63, + "blockHash": "0x1803dacb914fcad724814b7ca2a85d08c6b6d389ea6dd9b0efc8777cea154379" + } + ], + "blockNumber": 17743222, + "cumulativeGasUsed": "4803790", + "status": 1, + "byzantium": true + }, + "args": [ + "0xc944E90C64B2c07662A292be6244BDf05Cda44a7", + "0x1231A8579CA4208F8AE6fecC6c96bf935B73487D" + ], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x67d67a567bceb363ddb199b1e4ab06e7a99f16e034e03086971a332c09ec5c0e\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003c8f38038062003c8f83398181016040528101906200003791906200039c565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004e7565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b505062000596565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001f26200034560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200024b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024290620004c5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b590620004a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000815190506200037f8162000562565b92915050565b60008151905062000396816200057c565b92915050565b60008060408385031215620003b057600080fd5b6000620003c08582860162000385565b9250506020620003d3858286016200036e565b9150509250929050565b6000620003ec60198362000509565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006200042e60208362000509565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200047060148362000509565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004be81620003dd565b9050919050565b60006020820190508181036000830152620004e0816200041f565b9050919050565b60006020820190508181036000830152620005028162000461565b9050919050565b600082825260208201905092915050565b6000620005278262000542565b9050919050565b60006200053b826200051a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200056d816200051a565b81146200057957600080fd5b50565b62000587816200052e565b81146200059357600080fd5b50565b6136e980620005a66000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80638da5cb5b116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80638da5cb5b146102875780639c05fc60146102a5578063a3457466146102c1578063a619486e146102df578063b6b55f25146102fd5761012c565b80635975e00c116100f45780635975e00c146101e557806368d30c2e146102015780636e03b8dc1461021d578063715018a61461024d57806379ee1bdf146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d57806343fb93d914610199578063463013a2146101c9575b600080fd5b61014b6004803603810190610146919061253a565b6103bb565b005b61016760048036038101906101629190612511565b610563565b6040516101749190613029565b60405180910390f35b610197600480360381019061019291906125d7565b6105a4565b005b6101b360048036038101906101ae91906124c2565b610701565b6040516101c09190612e63565b60405180910390f35b6101e360048036038101906101de919061257f565b610726565b005b6101ff60048036038101906101fa9190612335565b6107b2565b005b61021b6004803603810190610216919061235e565b610943565b005b61023760048036038101906102329190612511565b610c8b565b6040516102449190612e63565b60405180910390f35b610255610cbe565b005b610271600480360381019061026c9190612335565b610df8565b60405161027e9190613029565b60405180910390f35b61028f610e15565b60405161029c9190612e63565b60405180910390f35b6102bf60048036038101906102ba9190612424565b610e3e565b005b6102c9610f6b565b6040516102d69190613007565b60405180910390f35b6102e7611043565b6040516102f49190612e63565b60405180910390f35b610317600480360381019061031291906125d7565b611069565b005b610333600480360381019061032e9190612335565b61114c565b005b61034f600480360381019061034a9190612335565b61126d565b005b61036b60048036038101906103669190612511565b6113e0565b6040516103789190612e63565b60405180910390f35b61039b60048036038101906103969190612335565b61145b565b005b6103a5611604565b6040516103b29190613044565b60405180910390f35b6103c361162e565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613225565b60405180910390fd5b60006104438383611636565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9868660405161055692919061305f565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113e0565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac61162e565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613225565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613205565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613305565b60405180910390a250565b600061071d846107108561174a565b80519060200120846117c0565b90509392505050565b61072e61162e565b73ffffffffffffffffffffffffffffffffffffffff1661074c610e15565b73ffffffffffffffffffffffffffffffffffffffff16146107a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079990613225565b60405180910390fd5b6107ad838383611804565b505050565b6107ba61162e565b73ffffffffffffffffffffffffffffffffffffffff166107d8610e15565b73ffffffffffffffffffffffffffffffffffffffff161461082e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082590613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561089e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089590613105565b60405180910390fd5b6108b28160026119e690919063ffffffff16565b6108f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e890613265565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960016040516109389190613029565b60405180910390a250565b61094b61162e565b73ffffffffffffffffffffffffffffffffffffffff16610969610e15565b73ffffffffffffffffffffffffffffffffffffffff16146109bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b690613225565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a1b9190612e63565b60206040518083038186803b158015610a3357600080fd5b505afa158015610a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6b9190612600565b1015610aac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa390613145565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610afd9b9a99989796959493929190612e7e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b928280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a16565b9050610be1818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c76989796959493929190612f89565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cc661162e565b73ffffffffffffffffffffffffffffffffffffffff16610ce4610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610d3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3190613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e0e826002611a9290919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e4661162e565b73ffffffffffffffffffffffffffffffffffffffff16610e64610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610eba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb190613225565b60405180910390fd5b818190508484905014610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef9906130e5565b60405180910390fd5b60005b84849050811015610f6457610f57858583818110610f1f57fe5b9050602002810190610f319190613320565b858585818110610f3d57fe5b9050602002016020810190610f529190612335565b611804565b8080600101915050610f05565b5050505050565b606080610f786002611ac2565b67ffffffffffffffff81118015610f8e57600080fd5b50604051908082528060200260200182016040528015610fbd5781602001602082028036833780820191505090505b50905060005b610fcd6002611ac2565b81101561103b57610fe8816002611ad790919063ffffffff16565b828281518110610ff457fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fc3565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116110ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a390613205565b60405180910390fd5b6110fb333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611af1909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111419190613305565b60405180910390a250565b61115461162e565b73ffffffffffffffffffffffffffffffffffffffff16611172610e15565b73ffffffffffffffffffffffffffffffffffffffff16146111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf90613225565b60405180910390fd5b6111dc816002611b7a90919063ffffffff16565b61121b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121290613185565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516112629190613029565b60405180910390a250565b61127561162e565b73ffffffffffffffffffffffffffffffffffffffff16611293610e15565b73ffffffffffffffffffffffffffffffffffffffff16146112e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112e090613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611359576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611350906131a5565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61146361162e565b73ffffffffffffffffffffffffffffffffffffffff16611481610e15565b73ffffffffffffffffffffffffffffffffffffffff16146114d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ce90613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153e90613125565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116bc83836040516024016040516020818303038152906040529190604051611662929190612e4a565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611baa565b905092915050565b6117458363a9059cbb60e01b84846040516024016116e3929190612f60565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b9050838383836040516020016117a69493929190612d97565b604051602081830303815290604052945050505050919050565b60008060ff60f81b8386866040516020016117de9493929190612de5565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161186a906131c5565b60405180910390fd5b61187c81611cc9565b6118bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b2906132e5565b60405180910390fd5b60006118c78484611636565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516119d892919061305f565b60405180910390a450505050565b6000611a0e836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cdc565b905092915050565b600080611a2d600086611a288761174a565b611d4c565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611a8757611a858184611e5d565b505b809150509392505050565b6000611aba836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ea7565b905092915050565b6000611ad082600001611eca565b9050919050565b6000611ae68360000183611edb565b60001c905092915050565b611b74846323b872dd60e01b858585604051602401611b1293929190612f29565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b50505050565b6000611ba2836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f48565b905092915050565b60006004825114611bf0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be790613245565b60405180910390fd5b60006020830151905080915050919050565b6060611c64826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120309092919063ffffffff16565b9050600081511115611cc45780806020019051810190611c849190612499565b611cc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cba906132a5565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611ce88383611ea7565b611d41578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d46565b600090505b92915050565b60008084471015611d92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d89906132c5565b60405180910390fd5b600083511415611dd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dce906130c5565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e49906131e5565b60405180910390fd5b809150509392505050565b6060611e9f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612030565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1d906130a5565b60405180910390fd5b826000018281548110611f3557fe5b9060005260206000200154905092915050565b600080836001016000848152602001908152602001600020549050600081146120245760006001820390506000600186600001805490500390506000866000018281548110611f9357fe5b9060005260206000200154905080876000018481548110611fb057fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fe857fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061202a565b60009150505b92915050565b606061203f8484600085612048565b90509392505050565b60608247101561208d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208490613165565b60405180910390fd5b61209685611cc9565b6120d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120cc90613285565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516120ff9190612e33565b60006040518083038185875af1925050503d806000811461213c576040519150601f19603f3d011682016040523d82523d6000602084013e612141565b606091505b509150915061215182828661215d565b92505050949350505050565b6060831561216d578290506121bd565b6000835111156121805782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121b49190613083565b60405180910390fd5b9392505050565b6000813590506121d381613630565b92915050565b60008083601f8401126121eb57600080fd5b8235905067ffffffffffffffff81111561220457600080fd5b60208301915083602082028301111561221c57600080fd5b9250929050565b60008083601f84011261223557600080fd5b8235905067ffffffffffffffff81111561224e57600080fd5b60208301915083602082028301111561226657600080fd5b9250929050565b60008151905061227c81613647565b92915050565b6000813590506122918161365e565b92915050565b6000813590506122a681613675565b92915050565b6000813590506122bb8161368c565b92915050565b60008083601f8401126122d357600080fd5b8235905067ffffffffffffffff8111156122ec57600080fd5b60208301915083600182028301111561230457600080fd5b9250929050565b60008135905061231a8161369c565b92915050565b60008151905061232f8161369c565b92915050565b60006020828403121561234757600080fd5b6000612355848285016121c4565b91505092915050565b60008060008060008060008060006101208a8c03121561237d57600080fd5b600061238b8c828d016121c4565b995050602061239c8c828d016121c4565b98505060406123ad8c828d0161230b565b97505060606123be8c828d0161230b565b96505060806123cf8c828d0161230b565b95505060a06123e08c828d0161230b565b94505060c06123f18c828d0161230b565b93505060e06124028c828d0161230b565b9250506101006124148c828d016122ac565b9150509295985092959850929598565b6000806000806040858703121561243a57600080fd5b600085013567ffffffffffffffff81111561245457600080fd5b61246087828801612223565b9450945050602085013567ffffffffffffffff81111561247f57600080fd5b61248b878288016121d9565b925092505092959194509250565b6000602082840312156124ab57600080fd5b60006124b98482850161226d565b91505092915050565b6000806000606084860312156124d757600080fd5b60006124e586828701612282565b93505060206124f6868287016121c4565b9250506040612507868287016121c4565b9150509250925092565b60006020828403121561252357600080fd5b600061253184828501612297565b91505092915050565b6000806020838503121561254d57600080fd5b600083013567ffffffffffffffff81111561256757600080fd5b612573858286016122c1565b92509250509250929050565b60008060006040848603121561259457600080fd5b600084013567ffffffffffffffff8111156125ae57600080fd5b6125ba868287016122c1565b935093505060206125cd868287016121c4565b9150509250925092565b6000602082840312156125e957600080fd5b60006125f78482850161230b565b91505092915050565b60006020828403121561261257600080fd5b600061262084828501612320565b91505092915050565b60006126358383612641565b60208301905092915050565b61264a816133ed565b82525050565b612659816133ed565b82525050565b61267061266b826133ed565b6135a6565b82525050565b600061268182613387565b61268b81856133b5565b935061269683613377565b8060005b838110156126c75781516126ae8882612629565b97506126b9836133a8565b92505060018101905061269a565b5085935050505092915050565b6126dd816133ff565b82525050565b6126f46126ef82613437565b6135c2565b82525050565b61270b61270682613463565b6135cc565b82525050565b61272261271d8261340b565b6135b8565b82525050565b6127396127348261348f565b6135d6565b82525050565b61275061274b826134bb565b6135e0565b82525050565b600061276182613392565b61276b81856133c6565b935061277b818560208601613573565b80840191505092915050565b6127908161352e565b82525050565b61279f81613552565b82525050565b60006127b183856133d1565b93506127be838584613564565b6127c7836135fe565b840190509392505050565b60006127de83856133e2565b93506127eb838584613564565b82840190509392505050565b60006128028261339d565b61280c81856133d1565b935061281c818560208601613573565b612825816135fe565b840191505092915050565b600061283d6022836133d1565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a36020836133d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e36015836133d1565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612923601a836133d1565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129636026836133d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129c96020836133d1565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a096026836133d1565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a6f601b836133d1565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612aaf6019836133d1565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612aef601d836133d1565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b2f6019836133d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b6f6015836133d1565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612baf6020836133d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bef6018836133d1565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c2f6019836133d1565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c6f601d836133d1565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612caf602a836133d1565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d15601d836133d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d556019836133d1565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9181613524565b82525050565b6000612da382876126e3565b600a82019150612db382866126e3565b600a82019150612dc38285612728565b601482019150612dd382846126fa565b600f8201915081905095945050505050565b6000612df18287612711565b600182019150612e01828661265f565b601482019150612e11828561273f565b602082019150612e21828461273f565b60208201915081905095945050505050565b6000612e3f8284612756565b915081905092915050565b6000612e578284866127d2565b91508190509392505050565b6000602082019050612e786000830184612650565b92915050565b600061016082019050612e94600083018e612650565b612ea1602083018d612650565b612eae604083018c612650565b612ebb606083018b612650565b612ec8608083018a612d88565b612ed560a0830189612d88565b612ee260c0830188612d88565b612eef60e0830187612d88565b612efd610100830186612d88565b612f0b610120830185612d88565b612f19610140830184612796565b9c9b505050505050505050505050565b6000606082019050612f3e6000830186612650565b612f4b6020830185612650565b612f586040830184612d88565b949350505050565b6000604082019050612f756000830185612650565b612f826020830184612d88565b9392505050565b600061010082019050612f9f600083018b612650565b612fac602083018a612d88565b612fb96040830189612d88565b612fc66060830188612d88565b612fd36080830187612d88565b612fe060a0830186612d88565b612fed60c0830185612d88565b612ffa60e0830184612796565b9998505050505050505050565b600060208201905081810360008301526130218184612676565b905092915050565b600060208201905061303e60008301846126d4565b92915050565b60006020820190506130596000830184612787565b92915050565b6000602082019050818103600083015261307a8184866127a5565b90509392505050565b6000602082019050818103600083015261309d81846127f7565b905092915050565b600060208201905081810360008301526130be81612830565b9050919050565b600060208201905081810360008301526130de81612896565b9050919050565b600060208201905081810360008301526130fe816128d6565b9050919050565b6000602082019050818103600083015261311e81612916565b9050919050565b6000602082019050818103600083015261313e81612956565b9050919050565b6000602082019050818103600083015261315e816129bc565b9050919050565b6000602082019050818103600083015261317e816129fc565b9050919050565b6000602082019050818103600083015261319e81612a62565b9050919050565b600060208201905081810360008301526131be81612aa2565b9050919050565b600060208201905081810360008301526131de81612ae2565b9050919050565b600060208201905081810360008301526131fe81612b22565b9050919050565b6000602082019050818103600083015261321e81612b62565b9050919050565b6000602082019050818103600083015261323e81612ba2565b9050919050565b6000602082019050818103600083015261325e81612be2565b9050919050565b6000602082019050818103600083015261327e81612c22565b9050919050565b6000602082019050818103600083015261329e81612c62565b9050919050565b600060208201905081810360008301526132be81612ca2565b9050919050565b600060208201905081810360008301526132de81612d08565b9050919050565b600060208201905081810360008301526132fe81612d48565b9050919050565b600060208201905061331a6000830184612d88565b92915050565b6000808335600160200384360303811261333957600080fd5b80840192508235915067ffffffffffffffff82111561335757600080fd5b60208301925060018202360383131561336f57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133f882613504565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506134ff8261361c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353982613540565b9050919050565b600061354b82613504565b9050919050565b600061355d826134f1565b9050919050565b82818337600083830152505050565b60005b83811015613591578082015181840152602081019050613576565b838111156135a0576000848401525b50505050565b60006135b1826135ea565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f58261360f565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061362d5761362c6135fc565b5b50565b613639816133ed565b811461364457600080fd5b50565b613650816133ff565b811461365b57600080fd5b50565b613667816134bb565b811461367257600080fd5b50565b61367e816134c5565b811461368957600080fd5b50565b6003811061369957600080fd5b50565b6136a581613524565b81146136b057600080fd5b5056fea2646970667358221220d5c9f5b6d4e12c49170d8830f9459ebc2386434f550d65bae2bbc0fcfbacfb6264736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80638da5cb5b116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80638da5cb5b146102875780639c05fc60146102a5578063a3457466146102c1578063a619486e146102df578063b6b55f25146102fd5761012c565b80635975e00c116100f45780635975e00c146101e557806368d30c2e146102015780636e03b8dc1461021d578063715018a61461024d57806379ee1bdf146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d57806343fb93d914610199578063463013a2146101c9575b600080fd5b61014b6004803603810190610146919061253a565b6103bb565b005b61016760048036038101906101629190612511565b610563565b6040516101749190613029565b60405180910390f35b610197600480360381019061019291906125d7565b6105a4565b005b6101b360048036038101906101ae91906124c2565b610701565b6040516101c09190612e63565b60405180910390f35b6101e360048036038101906101de919061257f565b610726565b005b6101ff60048036038101906101fa9190612335565b6107b2565b005b61021b6004803603810190610216919061235e565b610943565b005b61023760048036038101906102329190612511565b610c8b565b6040516102449190612e63565b60405180910390f35b610255610cbe565b005b610271600480360381019061026c9190612335565b610df8565b60405161027e9190613029565b60405180910390f35b61028f610e15565b60405161029c9190612e63565b60405180910390f35b6102bf60048036038101906102ba9190612424565b610e3e565b005b6102c9610f6b565b6040516102d69190613007565b60405180910390f35b6102e7611043565b6040516102f49190612e63565b60405180910390f35b610317600480360381019061031291906125d7565b611069565b005b610333600480360381019061032e9190612335565b61114c565b005b61034f600480360381019061034a9190612335565b61126d565b005b61036b60048036038101906103669190612511565b6113e0565b6040516103789190612e63565b60405180910390f35b61039b60048036038101906103969190612335565b61145b565b005b6103a5611604565b6040516103b29190613044565b60405180910390f35b6103c361162e565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613225565b60405180910390fd5b60006104438383611636565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9868660405161055692919061305f565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113e0565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac61162e565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613225565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613205565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613305565b60405180910390a250565b600061071d846107108561174a565b80519060200120846117c0565b90509392505050565b61072e61162e565b73ffffffffffffffffffffffffffffffffffffffff1661074c610e15565b73ffffffffffffffffffffffffffffffffffffffff16146107a2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161079990613225565b60405180910390fd5b6107ad838383611804565b505050565b6107ba61162e565b73ffffffffffffffffffffffffffffffffffffffff166107d8610e15565b73ffffffffffffffffffffffffffffffffffffffff161461082e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161082590613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561089e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089590613105565b60405180910390fd5b6108b28160026119e690919063ffffffff16565b6108f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108e890613265565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960016040516109389190613029565b60405180910390a250565b61094b61162e565b73ffffffffffffffffffffffffffffffffffffffff16610969610e15565b73ffffffffffffffffffffffffffffffffffffffff16146109bf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109b690613225565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a1b9190612e63565b60206040518083038186803b158015610a3357600080fd5b505afa158015610a47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a6b9190612600565b1015610aac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610aa390613145565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610afd9b9a99989796959493929190612e7e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b928280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a16565b9050610be1818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116c49092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c76989796959493929190612f89565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cc661162e565b73ffffffffffffffffffffffffffffffffffffffff16610ce4610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610d3a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d3190613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e0e826002611a9290919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e4661162e565b73ffffffffffffffffffffffffffffffffffffffff16610e64610e15565b73ffffffffffffffffffffffffffffffffffffffff1614610eba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eb190613225565b60405180910390fd5b818190508484905014610f02576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ef9906130e5565b60405180910390fd5b60005b84849050811015610f6457610f57858583818110610f1f57fe5b9050602002810190610f319190613320565b858585818110610f3d57fe5b9050602002016020810190610f529190612335565b611804565b8080600101915050610f05565b5050505050565b606080610f786002611ac2565b67ffffffffffffffff81118015610f8e57600080fd5b50604051908082528060200260200182016040528015610fbd5781602001602082028036833780820191505090505b50905060005b610fcd6002611ac2565b81101561103b57610fe8816002611ad790919063ffffffff16565b828281518110610ff457fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fc3565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116110ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110a390613205565b60405180910390fd5b6110fb333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611af1909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111419190613305565b60405180910390a250565b61115461162e565b73ffffffffffffffffffffffffffffffffffffffff16611172610e15565b73ffffffffffffffffffffffffffffffffffffffff16146111c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111bf90613225565b60405180910390fd5b6111dc816002611b7a90919063ffffffff16565b61121b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161121290613185565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516112629190613029565b60405180910390a250565b61127561162e565b73ffffffffffffffffffffffffffffffffffffffff16611293610e15565b73ffffffffffffffffffffffffffffffffffffffff16146112e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112e090613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611359576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611350906131a5565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61146361162e565b73ffffffffffffffffffffffffffffffffffffffff16611481610e15565b73ffffffffffffffffffffffffffffffffffffffff16146114d7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114ce90613225565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611547576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161153e90613125565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116bc83836040516024016040516020818303038152906040529190604051611662929190612e4a565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611baa565b905092915050565b6117458363a9059cbb60e01b84846040516024016116e3929190612f60565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b9050838383836040516020016117a69493929190612d97565b604051602081830303815290604052945050505050919050565b60008060ff60f81b8386866040516020016117de9493929190612de5565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611873576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161186a906131c5565b60405180910390fd5b61187c81611cc9565b6118bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118b2906132e5565b60405180910390fd5b60006118c78484611636565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c987876040516119d892919061305f565b60405180910390a450505050565b6000611a0e836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cdc565b905092915050565b600080611a2d600086611a288761174a565b611d4c565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611a8757611a858184611e5d565b505b809150509392505050565b6000611aba836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ea7565b905092915050565b6000611ad082600001611eca565b9050919050565b6000611ae68360000183611edb565b60001c905092915050565b611b74846323b872dd60e01b858585604051602401611b1293929190612f29565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c02565b50505050565b6000611ba2836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f48565b905092915050565b60006004825114611bf0576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be790613245565b60405180910390fd5b60006020830151905080915050919050565b6060611c64826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120309092919063ffffffff16565b9050600081511115611cc45780806020019051810190611c849190612499565b611cc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cba906132a5565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611ce88383611ea7565b611d41578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d46565b600090505b92915050565b60008084471015611d92576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d89906132c5565b60405180910390fd5b600083511415611dd7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dce906130c5565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e52576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e49906131e5565b60405180910390fd5b809150509392505050565b6060611e9f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612030565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1d906130a5565b60405180910390fd5b826000018281548110611f3557fe5b9060005260206000200154905092915050565b600080836001016000848152602001908152602001600020549050600081146120245760006001820390506000600186600001805490500390506000866000018281548110611f9357fe5b9060005260206000200154905080876000018481548110611fb057fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fe857fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061202a565b60009150505b92915050565b606061203f8484600085612048565b90509392505050565b60608247101561208d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161208490613165565b60405180910390fd5b61209685611cc9565b6120d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120cc90613285565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516120ff9190612e33565b60006040518083038185875af1925050503d806000811461213c576040519150601f19603f3d011682016040523d82523d6000602084013e612141565b606091505b509150915061215182828661215d565b92505050949350505050565b6060831561216d578290506121bd565b6000835111156121805782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121b49190613083565b60405180910390fd5b9392505050565b6000813590506121d381613630565b92915050565b60008083601f8401126121eb57600080fd5b8235905067ffffffffffffffff81111561220457600080fd5b60208301915083602082028301111561221c57600080fd5b9250929050565b60008083601f84011261223557600080fd5b8235905067ffffffffffffffff81111561224e57600080fd5b60208301915083602082028301111561226657600080fd5b9250929050565b60008151905061227c81613647565b92915050565b6000813590506122918161365e565b92915050565b6000813590506122a681613675565b92915050565b6000813590506122bb8161368c565b92915050565b60008083601f8401126122d357600080fd5b8235905067ffffffffffffffff8111156122ec57600080fd5b60208301915083600182028301111561230457600080fd5b9250929050565b60008135905061231a8161369c565b92915050565b60008151905061232f8161369c565b92915050565b60006020828403121561234757600080fd5b6000612355848285016121c4565b91505092915050565b60008060008060008060008060006101208a8c03121561237d57600080fd5b600061238b8c828d016121c4565b995050602061239c8c828d016121c4565b98505060406123ad8c828d0161230b565b97505060606123be8c828d0161230b565b96505060806123cf8c828d0161230b565b95505060a06123e08c828d0161230b565b94505060c06123f18c828d0161230b565b93505060e06124028c828d0161230b565b9250506101006124148c828d016122ac565b9150509295985092959850929598565b6000806000806040858703121561243a57600080fd5b600085013567ffffffffffffffff81111561245457600080fd5b61246087828801612223565b9450945050602085013567ffffffffffffffff81111561247f57600080fd5b61248b878288016121d9565b925092505092959194509250565b6000602082840312156124ab57600080fd5b60006124b98482850161226d565b91505092915050565b6000806000606084860312156124d757600080fd5b60006124e586828701612282565b93505060206124f6868287016121c4565b9250506040612507868287016121c4565b9150509250925092565b60006020828403121561252357600080fd5b600061253184828501612297565b91505092915050565b6000806020838503121561254d57600080fd5b600083013567ffffffffffffffff81111561256757600080fd5b612573858286016122c1565b92509250509250929050565b60008060006040848603121561259457600080fd5b600084013567ffffffffffffffff8111156125ae57600080fd5b6125ba868287016122c1565b935093505060206125cd868287016121c4565b9150509250925092565b6000602082840312156125e957600080fd5b60006125f78482850161230b565b91505092915050565b60006020828403121561261257600080fd5b600061262084828501612320565b91505092915050565b60006126358383612641565b60208301905092915050565b61264a816133ed565b82525050565b612659816133ed565b82525050565b61267061266b826133ed565b6135a6565b82525050565b600061268182613387565b61268b81856133b5565b935061269683613377565b8060005b838110156126c75781516126ae8882612629565b97506126b9836133a8565b92505060018101905061269a565b5085935050505092915050565b6126dd816133ff565b82525050565b6126f46126ef82613437565b6135c2565b82525050565b61270b61270682613463565b6135cc565b82525050565b61272261271d8261340b565b6135b8565b82525050565b6127396127348261348f565b6135d6565b82525050565b61275061274b826134bb565b6135e0565b82525050565b600061276182613392565b61276b81856133c6565b935061277b818560208601613573565b80840191505092915050565b6127908161352e565b82525050565b61279f81613552565b82525050565b60006127b183856133d1565b93506127be838584613564565b6127c7836135fe565b840190509392505050565b60006127de83856133e2565b93506127eb838584613564565b82840190509392505050565b60006128028261339d565b61280c81856133d1565b935061281c818560208601613573565b612825816135fe565b840191505092915050565b600061283d6022836133d1565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a36020836133d1565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e36015836133d1565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612923601a836133d1565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129636026836133d1565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129c96020836133d1565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a096026836133d1565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a6f601b836133d1565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612aaf6019836133d1565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612aef601d836133d1565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b2f6019836133d1565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b6f6015836133d1565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612baf6020836133d1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bef6018836133d1565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c2f6019836133d1565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c6f601d836133d1565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612caf602a836133d1565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d15601d836133d1565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d556019836133d1565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9181613524565b82525050565b6000612da382876126e3565b600a82019150612db382866126e3565b600a82019150612dc38285612728565b601482019150612dd382846126fa565b600f8201915081905095945050505050565b6000612df18287612711565b600182019150612e01828661265f565b601482019150612e11828561273f565b602082019150612e21828461273f565b60208201915081905095945050505050565b6000612e3f8284612756565b915081905092915050565b6000612e578284866127d2565b91508190509392505050565b6000602082019050612e786000830184612650565b92915050565b600061016082019050612e94600083018e612650565b612ea1602083018d612650565b612eae604083018c612650565b612ebb606083018b612650565b612ec8608083018a612d88565b612ed560a0830189612d88565b612ee260c0830188612d88565b612eef60e0830187612d88565b612efd610100830186612d88565b612f0b610120830185612d88565b612f19610140830184612796565b9c9b505050505050505050505050565b6000606082019050612f3e6000830186612650565b612f4b6020830185612650565b612f586040830184612d88565b949350505050565b6000604082019050612f756000830185612650565b612f826020830184612d88565b9392505050565b600061010082019050612f9f600083018b612650565b612fac602083018a612d88565b612fb96040830189612d88565b612fc66060830188612d88565b612fd36080830187612d88565b612fe060a0830186612d88565b612fed60c0830185612d88565b612ffa60e0830184612796565b9998505050505050505050565b600060208201905081810360008301526130218184612676565b905092915050565b600060208201905061303e60008301846126d4565b92915050565b60006020820190506130596000830184612787565b92915050565b6000602082019050818103600083015261307a8184866127a5565b90509392505050565b6000602082019050818103600083015261309d81846127f7565b905092915050565b600060208201905081810360008301526130be81612830565b9050919050565b600060208201905081810360008301526130de81612896565b9050919050565b600060208201905081810360008301526130fe816128d6565b9050919050565b6000602082019050818103600083015261311e81612916565b9050919050565b6000602082019050818103600083015261313e81612956565b9050919050565b6000602082019050818103600083015261315e816129bc565b9050919050565b6000602082019050818103600083015261317e816129fc565b9050919050565b6000602082019050818103600083015261319e81612a62565b9050919050565b600060208201905081810360008301526131be81612aa2565b9050919050565b600060208201905081810360008301526131de81612ae2565b9050919050565b600060208201905081810360008301526131fe81612b22565b9050919050565b6000602082019050818103600083015261321e81612b62565b9050919050565b6000602082019050818103600083015261323e81612ba2565b9050919050565b6000602082019050818103600083015261325e81612be2565b9050919050565b6000602082019050818103600083015261327e81612c22565b9050919050565b6000602082019050818103600083015261329e81612c62565b9050919050565b600060208201905081810360008301526132be81612ca2565b9050919050565b600060208201905081810360008301526132de81612d08565b9050919050565b600060208201905081810360008301526132fe81612d48565b9050919050565b600060208201905061331a6000830184612d88565b92915050565b6000808335600160200384360303811261333957600080fd5b80840192508235915067ffffffffffffffff82111561335757600080fd5b60208301925060018202360383131561336f57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133f882613504565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506134ff8261361c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353982613540565b9050919050565b600061354b82613504565b9050919050565b600061355d826134f1565b9050919050565b82818337600083830152505050565b60005b83811015613591578082015181840152602081019050613576565b838111156135a0576000848401525b50505050565b60006135b1826135ea565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f58261360f565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061362d5761362c6135fc565b5b50565b613639816133ed565b811461364457600080fd5b50565b613650816133ff565b811461365b57600080fd5b50565b613667816134bb565b811461367257600080fd5b50565b61367e816134c5565b811461368957600080fd5b50565b6003811061369957600080fd5b50565b6136a581613524565b81146136b057600080fd5b5056fea2646970667358221220d5c9f5b6d4e12c49170d8830f9459ebc2386434f550d65bae2bbc0fcfbacfb6264736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Migrations.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Migrations.json new file mode 100644 index 000000000..0d08ba652 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Migrations.json @@ -0,0 +1,926 @@ +{ + "address": "0xfe69D738344050F3b4351428Ddc18577d1e4D21A", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xbf444265f96c20ae89d8126a2ead6ba4a6c48a7d73e59a3a8e6a675ef121b742", + "receipt": { + "to": null, + "from": "0xE04FcE05E9B8d21521bd1B0f069982c03BD31F76", + "contractAddress": "0xfe69D738344050F3b4351428Ddc18577d1e4D21A", + "transactionIndex": 93, + "gasUsed": "3166292", + "logsBloom": "0x00000000000000000000000000000000004004020000000000800000000000000000000000000000000002000000000000000000000000000000000000000000000004000000000000000000000000000001000000000000000000400000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000044000000000000000000000000000008000004000000000000000000000000000000000000000020000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x98555cef5de941d3d10d21c9a7db2c36fb76cc4bfd48376a5e61056b546c35a9", + "transactionHash": "0xbf444265f96c20ae89d8126a2ead6ba4a6c48a7d73e59a3a8e6a675ef121b742", + "logs": [ + { + "transactionIndex": 93, + "blockNumber": 16477321, + "transactionHash": "0xbf444265f96c20ae89d8126a2ead6ba4a6c48a7d73e59a3a8e6a675ef121b742", + "address": "0xfe69D738344050F3b4351428Ddc18577d1e4D21A", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e04fce05e9b8d21521bd1b0f069982c03bd31f76" + ], + "data": "0x", + "logIndex": 141, + "blockHash": "0x98555cef5de941d3d10d21c9a7db2c36fb76cc4bfd48376a5e61056b546c35a9" + }, + { + "transactionIndex": 93, + "blockNumber": 16477321, + "transactionHash": "0xbf444265f96c20ae89d8126a2ead6ba4a6c48a7d73e59a3a8e6a675ef121b742", + "address": "0xfe69D738344050F3b4351428Ddc18577d1e4D21A", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x000000000000000000000000ec188a659fd9e3caad5b14011a18b9f214d54eab" + ], + "data": "0x", + "logIndex": 142, + "blockHash": "0x98555cef5de941d3d10d21c9a7db2c36fb76cc4bfd48376a5e61056b546c35a9" + } + ], + "blockNumber": 16477321, + "cumulativeGasUsed": "8726275", + "status": 1, + "byzantium": true + }, + "args": [ + "0xc944E90C64B2c07662A292be6244BDf05Cda44a7", + "0xec188A659fD9e3CAAD5b14011a18B9F214D54eab" + ], + "solcInputHash": "6f5e8f450f52dd96ebb796aa6620fee9", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address)\":{\"params\":{\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 private _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSignature(\\n \\\"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\\\",\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\\n external\\n override\\n onlyOwner\\n {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solium-disable-next-line security/no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x0384d62cb600eb4128baacf5bca60ea2cb0b68d2d013479daef65ed5f15446ef\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n// Based on https://eips.ethereum.org/EIPS/eip-1167\\ncontract MinimalProxyFactory is Ownable {\\n // -- Events --\\n\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\\n }\\n\\n /**\\n * @notice Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(\\n bytes32 _salt,\\n address _implementation,\\n bytes memory _data\\n ) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @notice Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x8aa3d50e714f92dc0ed6cc6d88fa8a18c948493103928f6092f98815b2c046ca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003c9338038062003c9383398181016040528101906200003791906200039c565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004e7565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b505062000596565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001f26200034560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200024b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024290620004c5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b590620004a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000815190506200037f8162000562565b92915050565b60008151905062000396816200057c565b92915050565b60008060408385031215620003b057600080fd5b6000620003c08582860162000385565b9250506020620003d3858286016200036e565b9150509250929050565b6000620003ec60198362000509565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006200042e60208362000509565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200047060148362000509565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004be81620003dd565b9050919050565b60006020820190508181036000830152620004e0816200041f565b9050919050565b60006020820190508181036000830152620005028162000461565b9050919050565b600082825260208201905092915050565b6000620005278262000542565b9050919050565b60006200053b826200051a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200056d816200051a565b81146200057957600080fd5b50565b62000587816200052e565b81146200059357600080fd5b50565b6136ed80620005a66000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address)": { + "params": { + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3316, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3318, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)1964_storage" + }, + { + "astId": 3320, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3322, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1045" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1045": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)1964_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 1963, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)1699_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)1699_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 1694, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 1698, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockManager.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager.json new file mode 100644 index 000000000..2c8565f39 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockManager.json @@ -0,0 +1,926 @@ +{ + "address": "0xa242759664F68e20e8f5c690a70b6116256914bf", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xf345b60759680b954a7a713f5b33cc8e80f3f94fc011505676dd897020888820", + "receipt": { + "to": null, + "from": "0xE04FcE05E9B8d21521bd1B0f069982c03BD31F76", + "contractAddress": "0xa242759664F68e20e8f5c690a70b6116256914bf", + "transactionIndex": 229, + "gasUsed": "3166292", + "logsBloom": "0x00000000000000000000000000000000000004000000000000800000000000000000000000002000000000000000000000000000000000080000000000000000000004000000000000000000000000000001000000000000000000400000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000040000000000000000000000000000008000000000000000000200000000000000000000000080020000020000000000000000000000000000000200000000000000000000000000000000000", + "blockHash": "0x424888f28081c0ad803b1dd628e41726f440f892b5d27f2cf1516f0ebe684c87", + "transactionHash": "0xf345b60759680b954a7a713f5b33cc8e80f3f94fc011505676dd897020888820", + "logs": [ + { + "transactionIndex": 229, + "blockNumber": 13863822, + "transactionHash": "0xf345b60759680b954a7a713f5b33cc8e80f3f94fc011505676dd897020888820", + "address": "0xa242759664F68e20e8f5c690a70b6116256914bf", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000e04fce05e9b8d21521bd1b0f069982c03bd31f76" + ], + "data": "0x", + "logIndex": 164, + "blockHash": "0x424888f28081c0ad803b1dd628e41726f440f892b5d27f2cf1516f0ebe684c87" + }, + { + "transactionIndex": 229, + "blockNumber": 13863822, + "transactionHash": "0xf345b60759680b954a7a713f5b33cc8e80f3f94fc011505676dd897020888820", + "address": "0xa242759664F68e20e8f5c690a70b6116256914bf", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x000000000000000000000000ce18fe70d6331f1ac403562202b4dc6ac41a10db" + ], + "data": "0x", + "logIndex": 165, + "blockHash": "0x424888f28081c0ad803b1dd628e41726f440f892b5d27f2cf1516f0ebe684c87" + } + ], + "blockNumber": 13863822, + "cumulativeGasUsed": "14596085", + "status": 1, + "byzantium": true + }, + "args": [ + "0xc944E90C64B2c07662A292be6244BDf05Cda44a7", + "0xcE18fE70D6331f1Ac403562202B4dc6AC41A10Db" + ], + "solcInputHash": "5ad03e035f8e3c63878532d87a315ef8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address)\":{\"params\":{\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 private _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSignature(\\n \\\"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\\\",\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\\n external\\n override\\n onlyOwner\\n {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solium-disable-next-line security/no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x0384d62cb600eb4128baacf5bca60ea2cb0b68d2d013479daef65ed5f15446ef\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n// Based on https://eips.ethereum.org/EIPS/eip-1167\\ncontract MinimalProxyFactory is Ownable {\\n // -- Events --\\n\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\\n }\\n\\n /**\\n * @notice Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(\\n bytes32 _salt,\\n address _implementation,\\n bytes memory _data\\n ) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @notice Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x8aa3d50e714f92dc0ed6cc6d88fa8a18c948493103928f6092f98815b2c046ca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003c9338038062003c9383398181016040528101906200003791906200039c565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004e7565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b505062000596565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001f26200034560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200024b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024290620004c5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b590620004a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000815190506200037f8162000562565b92915050565b60008151905062000396816200057c565b92915050565b60008060408385031215620003b057600080fd5b6000620003c08582860162000385565b9250506020620003d3858286016200036e565b9150509250929050565b6000620003ec60198362000509565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006200042e60208362000509565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200047060148362000509565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004be81620003dd565b9050919050565b60006020820190508181036000830152620004e0816200041f565b9050919050565b60006020820190508181036000830152620005028162000461565b9050919050565b600082825260208201905092915050565b6000620005278262000542565b9050919050565b60006200053b826200051a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200056d816200051a565b81146200057957600080fd5b50565b62000587816200052e565b81146200059357600080fd5b50565b6136ed80620005a66000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b6004803603810190610146919061253e565b6103bb565b005b61016760048036038101906101629190612515565b610563565b604051610174919061302d565b60405180910390f35b610197600480360381019061019291906125db565b6105a4565b005b6101b360048036038101906101ae9190612583565b610701565b005b6101cf60048036038101906101ca919061234c565b61078d565b005b6101eb60048036038101906101e69190612375565b61091e565b005b61020760048036038101906102029190612515565b610c7e565b6040516102149190612e67565b60405180910390f35b610225610cb1565b005b610241600480360381019061023c919061234c565b610deb565b60405161024e919061302d565b60405180910390f35b61025f610e08565b60405161026c9190612e67565b60405180910390f35b61028f600480360381019061028a919061243b565b610e31565b005b610299610f5e565b6040516102a6919061300b565b60405180910390f35b6102b7611036565b6040516102c49190612e67565b60405180910390f35b6102e760048036038101906102e291906125db565b61105c565b005b61030360048036038101906102fe91906124d9565b61113f565b6040516103109190612e67565b60405180910390f35b610333600480360381019061032e919061234c565b611163565b005b61034f600480360381019061034a919061234c565b611284565b005b61036b60048036038101906103669190612515565b6113f7565b6040516103789190612e67565b60405180910390f35b61039b6004803603810190610396919061234c565b611472565b005b6103a561161b565b6040516103b29190613048565b60405180910390f35b6103c3611645565b73ffffffffffffffffffffffffffffffffffffffff166103e1610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610437576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042e90613229565b60405180910390fd5b6000610443838361164d565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98686604051610556929190613063565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff16610585836113f7565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105ac611645565b73ffffffffffffffffffffffffffffffffffffffff166105ca610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610620576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161061790613229565b60405180910390fd5b60008111610663576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161065a90613209565b60405180910390fd5b6106b03382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516106f69190613309565b60405180910390a250565b610709611645565b73ffffffffffffffffffffffffffffffffffffffff16610727610e08565b73ffffffffffffffffffffffffffffffffffffffff161461077d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161077490613229565b60405180910390fd5b610788838383611761565b505050565b610795611645565b73ffffffffffffffffffffffffffffffffffffffff166107b3610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610809576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161080090613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610879576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087090613109565b60405180910390fd5b61088d81600261194390919063ffffffff16565b6108cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c390613269565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796001604051610913919061302d565b60405180910390a250565b610926611645565b73ffffffffffffffffffffffffffffffffffffffff16610944610e08565b73ffffffffffffffffffffffffffffffffffffffff161461099a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099190613229565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109f69190612e67565b60206040518083038186803b158015610a0e57600080fd5b505afa158015610a22573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a469190612604565b1015610a87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a7e90613149565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610ad09b9a99989796959493929190612e82565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610b858280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611973565b9050610bd4818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116db9092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610c69989796959493929190612f8d565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610cb9611645565b73ffffffffffffffffffffffffffffffffffffffff16610cd7610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610d2d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2490613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e018260026119ef90919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e39611645565b73ffffffffffffffffffffffffffffffffffffffff16610e57610e08565b73ffffffffffffffffffffffffffffffffffffffff1614610ead576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea490613229565b60405180910390fd5b818190508484905014610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906130e9565b60405180910390fd5b60005b84849050811015610f5757610f4a858583818110610f1257fe5b9050602002810190610f249190613324565b858585818110610f3057fe5b9050602002016020810190610f45919061234c565b611761565b8080600101915050610ef8565b5050505050565b606080610f6b6002611a1f565b67ffffffffffffffff81118015610f8157600080fd5b50604051908082528060200260200182016040528015610fb05781602001602082028036833780820191505090505b50905060005b610fc06002611a1f565b81101561102e57610fdb816002611a3490919063ffffffff16565b828281518110610fe757fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610fb6565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161109f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161109690613209565b60405180910390fd5b6110ee333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611a4e909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111349190613309565b60405180910390a250565b600061115b8361114e84611ad7565b8051906020012030611b4d565b905092915050565b61116b611645565b73ffffffffffffffffffffffffffffffffffffffff16611189610e08565b73ffffffffffffffffffffffffffffffffffffffff16146111df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111d690613229565b60405180910390fd5b6111f3816002611b9190919063ffffffff16565b611232576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161122990613189565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a796000604051611279919061302d565b60405180910390a250565b61128c611645565b73ffffffffffffffffffffffffffffffffffffffff166112aa610e08565b73ffffffffffffffffffffffffffffffffffffffff1614611300576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f790613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611370576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611367906131a9565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61147a611645565b73ffffffffffffffffffffffffffffffffffffffff16611498610e08565b73ffffffffffffffffffffffffffffffffffffffff16146114ee576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114e590613229565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561155e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161155590613129565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006116d383836040516024016040516020818303038152906040529190604051611679929190612e4e565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bc1565b905092915050565b61175c8363a9059cbb60e01b84846040516024016116fa929190612f64565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156117d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117c7906131c9565b60405180910390fd5b6117d981611ce0565b611818576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161180f906132e9565b60405180910390fd5b6000611824848461164d565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611935929190613063565b60405180910390a450505050565b600061196b836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611cf3565b905092915050565b60008061198a60008661198587611ad7565b611d63565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a26000835111156119e4576119e28184611e74565b505b809150509392505050565b6000611a17836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ebe565b905092915050565b6000611a2d82600001611ee1565b9050919050565b6000611a438360000183611ef2565b60001c905092915050565b611ad1846323b872dd60e01b858585604051602401611a6f93929190612f2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c19565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611b339493929190612d9b565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611b6b9493929190612de9565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611bb9836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f5f565b905092915050565b60006004825114611c07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611bfe90613249565b60405180910390fd5b60006020830151905080915050919050565b6060611c7b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120479092919063ffffffff16565b9050600081511115611cdb5780806020019051810190611c9b91906124b0565b611cda576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd1906132a9565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611cff8383611ebe565b611d58578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d5d565b600090505b92915050565b60008084471015611da9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da0906132c9565b60405180910390fd5b600083511415611dee576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611de5906130c9565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611e69576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e60906131e9565b60405180910390fd5b809150509392505050565b6060611eb683836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612047565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f34906130a9565b60405180910390fd5b826000018281548110611f4c57fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461203b5760006001820390506000600186600001805490500390506000866000018281548110611faa57fe5b9060005260206000200154905080876000018481548110611fc757fe5b9060005260206000200181905550600183018760010160008381526020019081526020016000208190555086600001805480611fff57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050612041565b60009150505b92915050565b6060612056848460008561205f565b90509392505050565b6060824710156120a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161209b90613169565b60405180910390fd5b6120ad85611ce0565b6120ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120e390613289565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516121169190612e37565b60006040518083038185875af1925050503d8060008114612153576040519150601f19603f3d011682016040523d82523d6000602084013e612158565b606091505b5091509150612168828286612174565b92505050949350505050565b60608315612184578290506121d4565b6000835111156121975782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121cb9190613087565b60405180910390fd5b9392505050565b6000813590506121ea81613634565b92915050565b60008083601f84011261220257600080fd5b8235905067ffffffffffffffff81111561221b57600080fd5b60208301915083602082028301111561223357600080fd5b9250929050565b60008083601f84011261224c57600080fd5b8235905067ffffffffffffffff81111561226557600080fd5b60208301915083602082028301111561227d57600080fd5b9250929050565b6000815190506122938161364b565b92915050565b6000813590506122a881613662565b92915050565b6000813590506122bd81613679565b92915050565b6000813590506122d281613690565b92915050565b60008083601f8401126122ea57600080fd5b8235905067ffffffffffffffff81111561230357600080fd5b60208301915083600182028301111561231b57600080fd5b9250929050565b600081359050612331816136a0565b92915050565b600081519050612346816136a0565b92915050565b60006020828403121561235e57600080fd5b600061236c848285016121db565b91505092915050565b60008060008060008060008060006101208a8c03121561239457600080fd5b60006123a28c828d016121db565b99505060206123b38c828d016121db565b98505060406123c48c828d01612322565b97505060606123d58c828d01612322565b96505060806123e68c828d01612322565b95505060a06123f78c828d01612322565b94505060c06124088c828d01612322565b93505060e06124198c828d01612322565b92505061010061242b8c828d016122c3565b9150509295985092959850929598565b6000806000806040858703121561245157600080fd5b600085013567ffffffffffffffff81111561246b57600080fd5b6124778782880161223a565b9450945050602085013567ffffffffffffffff81111561249657600080fd5b6124a2878288016121f0565b925092505092959194509250565b6000602082840312156124c257600080fd5b60006124d084828501612284565b91505092915050565b600080604083850312156124ec57600080fd5b60006124fa85828601612299565b925050602061250b858286016121db565b9150509250929050565b60006020828403121561252757600080fd5b6000612535848285016122ae565b91505092915050565b6000806020838503121561255157600080fd5b600083013567ffffffffffffffff81111561256b57600080fd5b612577858286016122d8565b92509250509250929050565b60008060006040848603121561259857600080fd5b600084013567ffffffffffffffff8111156125b257600080fd5b6125be868287016122d8565b935093505060206125d1868287016121db565b9150509250925092565b6000602082840312156125ed57600080fd5b60006125fb84828501612322565b91505092915050565b60006020828403121561261657600080fd5b600061262484828501612337565b91505092915050565b60006126398383612645565b60208301905092915050565b61264e816133f1565b82525050565b61265d816133f1565b82525050565b61267461266f826133f1565b6135aa565b82525050565b60006126858261338b565b61268f81856133b9565b935061269a8361337b565b8060005b838110156126cb5781516126b2888261262d565b97506126bd836133ac565b92505060018101905061269e565b5085935050505092915050565b6126e181613403565b82525050565b6126f86126f38261343b565b6135c6565b82525050565b61270f61270a82613467565b6135d0565b82525050565b6127266127218261340f565b6135bc565b82525050565b61273d61273882613493565b6135da565b82525050565b61275461274f826134bf565b6135e4565b82525050565b600061276582613396565b61276f81856133ca565b935061277f818560208601613577565b80840191505092915050565b61279481613532565b82525050565b6127a381613556565b82525050565b60006127b583856133d5565b93506127c2838584613568565b6127cb83613602565b840190509392505050565b60006127e283856133e6565b93506127ef838584613568565b82840190509392505050565b6000612806826133a1565b61281081856133d5565b9350612820818560208601613577565b61282981613602565b840191505092915050565b60006128416022836133d5565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006128a76020836133d5565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006128e76015836133d5565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612927601a836133d5565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129676026836133d5565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129cd6020836133d5565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a0d6026836133d5565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a73601b836133d5565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612ab36019836133d5565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612af3601d836133d5565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612b336019836133d5565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612b736015836133d5565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612bb36020836133d5565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612bf36018836133d5565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612c336019836133d5565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612c73601d836133d5565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612cb3602a836133d5565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d19601d836133d5565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612d596019836133d5565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612d9581613528565b82525050565b6000612da782876126e7565b600a82019150612db782866126e7565b600a82019150612dc7828561272c565b601482019150612dd782846126fe565b600f8201915081905095945050505050565b6000612df58287612715565b600182019150612e058286612663565b601482019150612e158285612743565b602082019150612e258284612743565b60208201915081905095945050505050565b6000612e43828461275a565b915081905092915050565b6000612e5b8284866127d6565b91508190509392505050565b6000602082019050612e7c6000830184612654565b92915050565b600061016082019050612e98600083018e612654565b612ea5602083018d612654565b612eb2604083018c612654565b612ebf606083018b612654565b612ecc608083018a612d8c565b612ed960a0830189612d8c565b612ee660c0830188612d8c565b612ef360e0830187612d8c565b612f01610100830186612d8c565b612f0f610120830185612d8c565b612f1d61014083018461279a565b9c9b505050505050505050505050565b6000606082019050612f426000830186612654565b612f4f6020830185612654565b612f5c6040830184612d8c565b949350505050565b6000604082019050612f796000830185612654565b612f866020830184612d8c565b9392505050565b600061010082019050612fa3600083018b612654565b612fb0602083018a612d8c565b612fbd6040830189612d8c565b612fca6060830188612d8c565b612fd76080830187612d8c565b612fe460a0830186612d8c565b612ff160c0830185612d8c565b612ffe60e083018461279a565b9998505050505050505050565b60006020820190508181036000830152613025818461267a565b905092915050565b600060208201905061304260008301846126d8565b92915050565b600060208201905061305d600083018461278b565b92915050565b6000602082019050818103600083015261307e8184866127a9565b90509392505050565b600060208201905081810360008301526130a181846127fb565b905092915050565b600060208201905081810360008301526130c281612834565b9050919050565b600060208201905081810360008301526130e28161289a565b9050919050565b60006020820190508181036000830152613102816128da565b9050919050565b600060208201905081810360008301526131228161291a565b9050919050565b600060208201905081810360008301526131428161295a565b9050919050565b60006020820190508181036000830152613162816129c0565b9050919050565b6000602082019050818103600083015261318281612a00565b9050919050565b600060208201905081810360008301526131a281612a66565b9050919050565b600060208201905081810360008301526131c281612aa6565b9050919050565b600060208201905081810360008301526131e281612ae6565b9050919050565b6000602082019050818103600083015261320281612b26565b9050919050565b6000602082019050818103600083015261322281612b66565b9050919050565b6000602082019050818103600083015261324281612ba6565b9050919050565b6000602082019050818103600083015261326281612be6565b9050919050565b6000602082019050818103600083015261328281612c26565b9050919050565b600060208201905081810360008301526132a281612c66565b9050919050565b600060208201905081810360008301526132c281612ca6565b9050919050565b600060208201905081810360008301526132e281612d0c565b9050919050565b6000602082019050818103600083015261330281612d4c565b9050919050565b600060208201905061331e6000830184612d8c565b92915050565b6000808335600160200384360303811261333d57600080fd5b80840192508235915067ffffffffffffffff82111561335b57600080fd5b60208301925060018202360383131561337357600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006133fc82613508565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061350382613620565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600061353d82613544565b9050919050565b600061354f82613508565b9050919050565b6000613561826134f5565b9050919050565b82818337600083830152505050565b60005b8381101561359557808201518184015260208101905061357a565b838111156135a4576000848401525b50505050565b60006135b5826135ee565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006135f982613613565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061363157613630613600565b5b50565b61363d816133f1565b811461364857600080fd5b50565b61365481613403565b811461365f57600080fd5b50565b61366b816134bf565b811461367657600080fd5b50565b613682816134c9565b811461368d57600080fd5b50565b6003811061369d57600080fd5b50565b6136a981613528565b81146136b457600080fd5b5056fea26469706673582212202d3d549e01583bc5460844b73df152769c2a77e8b1ca88724d847dbd95e3af7964736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address)": { + "params": { + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 7, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2439, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 2441, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)1461_storage" + }, + { + "astId": 2443, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 2445, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)542" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)542": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)1461_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 1460, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)1196_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)1196_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 1191, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 1195, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Foundation.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Foundation.json new file mode 100644 index 000000000..2bfc70eaf --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Foundation.json @@ -0,0 +1,1083 @@ +{ + "address": "0x624984fd288e28C0D24d7E0E4aDFDa130717720B", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x86a285707dd06466b0f7d7e9e6622d561013f6163865e82ee7fdab6253db5112", + "receipt": { + "to": null, + "from": "0xE04FcE05E9B8d21521bd1B0f069982c03BD31F76", + "contractAddress": "0x624984fd288e28C0D24d7E0E4aDFDa130717720B", + "transactionIndex": 85, + "gasUsed": "3482943", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x4c56d99203adc1acca5170c9f5b47bfe0559aab828956ae8978e6c5d72e204e3", + "transactionHash": "0x86a285707dd06466b0f7d7e9e6622d561013f6163865e82ee7fdab6253db5112", + "logs": [], + "blockNumber": 15877686, + "cumulativeGasUsed": "11372781", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "6f5e8f450f52dd96ebb796aa6620fee9", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n Ownable.initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0x21a1dae4105ba9ff6d9bc38bf983ee853976346562fa284f4b67a3c7ca91a2bf\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n uint256 private constant MAX_UINT256 = 2**256 - 1;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) private {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], MAX_UINT256);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5efc82d408fe81193664e67d614ca6299eafb00163ecc7819fad77cf0d35a2eb\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xc93c7362ac4d74b624b48517985f92c277ce90ae6e5ccb706e70a61af5752077\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613e61806100206000396000f3fe6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 4749, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2578, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "1", + "type": "t_contract(IERC20)1045" + }, + { + "astId": 2580, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 2582, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 2584, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 2586, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 2588, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 2590, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "7", + "type": "t_uint256" + }, + { + "astId": 2592, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 2594, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "9", + "type": "t_enum(Revocability)4426" + }, + { + "astId": 2596, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2598, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2600, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2602, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "10", + "type": "t_uint256" + }, + { + "astId": 2604, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "11", + "type": "t_uint256" + }, + { + "astId": 4021, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "12", + "type": "t_contract(IGraphTokenLockManager)4608" + }, + { + "astId": 4023, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "13", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1045": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)4608": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)4426": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-MIPs.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-MIPs.json new file mode 100644 index 000000000..6fbe025a9 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-MIPs.json @@ -0,0 +1,1101 @@ +{ + "address": "0x1231A8579CA4208F8AE6fecC6c96bf935B73487D", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0xf052d2bb33feac3417a266260dbb3daf166f553e35d8d9e325e8c7b9eda1de2e", + "receipt": { + "to": null, + "from": "0x8e623680d81372926a5878f544ceFE30B35BD9a0", + "contractAddress": "0x1231A8579CA4208F8AE6fecC6c96bf935B73487D", + "transactionIndex": 91, + "gasUsed": "3942206", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x21aa0703c20edf99b2a36778730d21e457d3282a6686211883105c10fed02757", + "transactionHash": "0xf052d2bb33feac3417a266260dbb3daf166f553e35d8d9e325e8c7b9eda1de2e", + "logs": [], + "blockNumber": 17743220, + "cumulativeGasUsed": "12662113", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "b5cdad58099d39cd1aed000b2fd864d8", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506146bb806100206000396000f3fe6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610b93578063e8dda6f514610bbc578063e97d87d514610be7578063ebbab99214610c12578063f2fde38b14610c3d578063fc0c546a14610c6657610295565b8063bc0163c114610ac0578063bd896dcb14610aeb578063ce845d1d14610b14578063d0ebdbe714610b3f578063d18e81b314610b6857610295565b806391f7cfb9116100fd57806391f7cfb9146109ff578063a4caeb4214610a2a578063b0d1818c14610a55578063b470aade14610a7e578063b6549f7514610aa957610295565b806386d00e021461095057806386d1a69f1461097b578063872a7810146109925780638a5bdf5c146109bd5780638da5cb5b146109d457610295565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108765780635b940081146108a157806360e79944146108cc578063715018a6146108e357806378e97925146108fa5780637bdf05af1461092557610295565b8063392e53cd1461079f578063398057a3146107ca57806344b1231f146107f557806345d30a1714610820578063481c6a751461084b57610295565b80632a627814116102195780632a627814146106dc5780632bc9ed02146106f35780633197cbb61461071e57806337aeb0861461074957806338af3eed1461077457610295565b8063029c6c9f1461061957806306040618146106445780630b80f7771461066f5780630dff24d5146106865780630fb5a6b4146106b157610295565b36610295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028c90613fb9565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c90614199565b60405180910390fd5b60003414610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035f90613fd9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103e99190613f2b565b60206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043991906131a5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a290614299565b60405180910390fd5b60006104b5610c91565b9050610506826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d43565b506001600281111561051457fe5b603b60009054906101000a900460ff16600281111561052f57fe5b141561061557600061053f610c91565b90508181101561058157600061055e8284610d8d90919063ffffffff16565b905061057581603f54610ddd90919063ffffffff16565b603f81905550506105c7565b60006105968383610d8d90919063ffffffff16565b9050603f548110156105bc576105b781603f54610d8d90919063ffffffff16565b6105bf565b60005b603f81905550505b6105cf610e32565b603f541115610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060a906141f9565b60405180910390fd5b505b5050005b34801561062557600080fd5b5061062e610ea1565b60405161063b9190614439565b60405180910390f35b34801561065057600080fd5b50610659610ebf565b6040516106669190614439565b60405180910390f35b34801561067b57600080fd5b50610684610efa565b005b34801561069257600080fd5b5061069b611067565b6040516106a89190614439565b60405180910390f35b3480156106bd57600080fd5b506106c66110ae565b6040516106d39190614439565b60405180910390f35b3480156106e857600080fd5b506106f16110cc565b005b3480156106ff57600080fd5b50610708611331565b6040516107159190613f10565b60405180910390f35b34801561072a57600080fd5b50610733611344565b6040516107409190614439565b60405180910390f35b34801561075557600080fd5b5061075e61134a565b60405161076b9190614439565b60405180910390f35b34801561078057600080fd5b50610789611350565b6040516107969190613ea3565b60405180910390f35b3480156107ab57600080fd5b506107b4611376565b6040516107c19190613f10565b60405180910390f35b3480156107d657600080fd5b506107df611389565b6040516107ec9190614439565b60405180910390f35b34801561080157600080fd5b5061080a610e32565b6040516108179190614439565b60405180910390f35b34801561082c57600080fd5b5061083561138f565b6040516108429190614439565b60405180910390f35b34801561085757600080fd5b50610860611395565b60405161086d9190613f61565b60405180910390f35b34801561088257600080fd5b5061088b6113bb565b6040516108989190613f10565b60405180910390f35b3480156108ad57600080fd5b506108b66113ce565b6040516108c39190614439565b60405180910390f35b3480156108d857600080fd5b506108e16114d9565b005b3480156108ef57600080fd5b506108f861171f565b005b34801561090657600080fd5b5061090f61186b565b60405161091c9190614439565b60405180910390f35b34801561093157600080fd5b5061093a611871565b6040516109479190614439565b60405180910390f35b34801561095c57600080fd5b506109656118ad565b6040516109729190614439565b60405180910390f35b34801561098757600080fd5b506109906118b3565b005b34801561099e57600080fd5b506109a7611a8f565b6040516109b49190613f7c565b60405180910390f35b3480156109c957600080fd5b506109d2611aa2565b005b3480156109e057600080fd5b506109e9611b7b565b6040516109f69190613ea3565b60405180910390f35b348015610a0b57600080fd5b50610a14611ba4565b604051610a219190614439565b60405180910390f35b348015610a3657600080fd5b50610a3f611c02565b604051610a4c9190614439565b60405180910390f35b348015610a6157600080fd5b50610a7c6004803603810190610a779190613328565b611c08565b005b348015610a8a57600080fd5b50610a93611e07565b604051610aa09190614439565b60405180910390f35b348015610ab557600080fd5b50610abe611e2a565b005b348015610acc57600080fd5b50610ad56120c2565b604051610ae29190614439565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d91906131ce565b6120f4565b005b348015610b2057600080fd5b50610b29610c91565b604051610b369190614439565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061317c565b61211c565b005b348015610b7457600080fd5b50610b7d6121b6565b604051610b8a9190614439565b60405180910390f35b348015610b9f57600080fd5b50610bba6004803603810190610bb5919061317c565b6121be565b005b348015610bc857600080fd5b50610bd1612339565b604051610bde9190614439565b60405180910390f35b348015610bf357600080fd5b50610bfc61233f565b604051610c099190614439565b60405180910390f35b348015610c1e57600080fd5b50610c27612345565b604051610c349190614439565b60405180910390f35b348015610c4957600080fd5b50610c646004803603810190610c5f919061317c565b612367565b005b348015610c7257600080fd5b50610c7b612522565b604051610c889190613f46565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cee9190613ea3565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613351565b905090565b6060610d8583836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b600082821115610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc9906140f9565b60405180910390fd5b818303905092915050565b600080828401905083811015610e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1f90614079565b60405180910390fd5b8091505092915050565b6000600280811115610e4057fe5b603b60009054906101000a900460ff166002811115610e5b57fe5b1415610e6b576035549050610e9e565b6000603a54118015610e855750603a54610e836121b6565b105b15610e935760009050610e9e565b610e9b611ba4565b90505b90565b6000610eba60385460355461256090919063ffffffff16565b905090565b6000610ef56001610ee7610ed1611e07565b610ed9611871565b61256090919063ffffffff16565b610ddd90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7f90614259565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514610fde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fd5906140d9565b60405180910390fd5b611039610fe9611b7b565b610ff1610c91565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611072610c91565b9050600061107e6120c2565b9050808211156110a45761109b8183610d8d90919063ffffffff16565b925050506110ab565b6000925050505b90565b60006110c7603654603754610d8d90919063ffffffff16565b905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461115c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115390614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111c657600080fd5b505afa1580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061120391906132be565b905060005b815181101561130157603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061125b57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b81526004016112a1929190613ee7565b602060405180830381600087803b1580156112bb57600080fd5b505af11580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f391906132ff565b508080600101915050611208565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156113dc57fe5b603b60009054906101000a900460ff1660028111156113f757fe5b141561140c5761140561263c565b90506114d6565b600060395411801561142657506039546114246121b6565b105b1561143457600090506114d6565b6001600281111561144157fe5b603b60009054906101000a900460ff16600281111561145c57fe5b14801561146b57506000603a54115b801561147f5750603a5461147d6121b6565b105b1561148d57600090506114d6565b60006114bf603f546114b1603c546114a3611ba4565b610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b90506114d26114cc610c91565b826126f6565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115d357600080fd5b505afa1580156115e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061161091906132be565b905060005b81518110156116ef57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061166857fe5b602002602001015160006040518363ffffffff1660e01b815260040161168f929190613ebe565b602060405180830381600087803b1580156116a957600080fd5b505af11580156116bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e191906132ff565b508080600101915050611615565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a490614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b60008061187c6121b6565b905060365481116118915760009150506118aa565b6118a660365482610d8d90919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90614359565b60405180910390fd5b600061194d6113ce565b905060008111611992576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611989906143b9565b60405180910390fd5b6119a781603c54610ddd90919063ffffffff16565b603c81905550611a1c603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611a849190614439565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2990614359565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611baf6121b6565b9050603654811015611bc5576000915050611bff565b603754811115611bda57603554915050611bff565b611bfb611be5610ea1565b611bed612345565b61270f90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8f90614359565b60405180910390fd5b60008111611cdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd2906141d9565b60405180910390fd5b80611ce4611067565b1015611d25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1c906142d9565b60405180910390fd5b611d94603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611dfc9190614439565b60405180910390a250565b6000611e25603854611e176110ae565b61256090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90614259565b60405180910390fd5b60016002811115611ec557fe5b603b60009054906101000a900460ff166002811115611ee057fe5b14611f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1790614319565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90614419565b60405180910390fd5b6000611f94611f83610e32565b603554610d8d90919063ffffffff16565b905060008111611fd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd090614099565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061204f612006611b7b565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516120b79190614439565b60405180910390a250565b60006120ef603d546120e1603c54603554610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b905090565b6121068a8a8a8a8a8a8a8a8a8a61277f565b61210f8b612c09565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146121aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a190614259565b60405180910390fd5b6121b381612c09565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461224e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224590614359565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b590614179565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d8160405161232e9190613ea3565b60405180910390a150565b603f5481565b60395481565b60006123626001612354610ebf565b610d8d90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ec90614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245c90614059565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606125578484600085612d87565b90509392505050565b60008082116125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259b90614159565b60405180910390fd5b8183816125ad57fe5b04905092915050565b6126378363a9059cbb60e01b84846040516024016125d5929190613ee7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612e9c565b505050565b60008060395411801561265757506039546126556121b6565b105b1561266557600090506126f3565b6001600281111561267257fe5b603b60009054906101000a900460ff16600281111561268d57fe5b14801561269c57506000603a54115b80156126b05750603a546126ae6121b6565b105b156126be57600090506126f3565b60006126dc603c546126ce611ba4565b610d8d90919063ffffffff16565b90506126ef6126e9610c91565b826126f6565b9150505b90565b60008183106127055781612707565b825b905092915050565b6000808314156127225760009050612779565b600082840290508284828161273357fe5b0414612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90614239565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff16156127cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c6906142f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561283f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612836906140b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128a6906143f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561291f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612916906143d9565b60405180910390fd5b60008711612962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295990614139565b60405180910390fd5b60008614156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299d90614279565b60405180910390fd5b8486106129e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129df90614019565b60405180910390fd5b6001841015612a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2390614219565b60405180910390fd5b60006002811115612a3957fe5b816002811115612a4557fe5b1415612a86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7d90614039565b60405180910390fd5b848310612ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612abf90614379565b60405180910390fd5b848210612b0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0190613ff9565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612b2e8a612f63565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612bf857fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7090614339565b60405180910390fd5b612c8281613001565b612cc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb8906141b9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015612dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dc390614119565b60405180910390fd5b612dd585613001565b612e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0b906142b9565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051612e3e9190613e8c565b60006040518083038185875af1925050503d8060008114612e7b576040519150601f19603f3d011682016040523d82523d6000602084013e612e80565b606091505b5091509150612e90828286613014565b92505050949350505050565b6060612efe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b9050600081511115612f5e5780806020019051810190612f1e91906132ff565b612f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5490614399565b60405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b6060831561302457829050613074565b6000835111156130375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b9190613f97565b60405180910390fd5b9392505050565b60008135905061308a81614630565b92915050565b60008151905061309f81614630565b92915050565b600082601f8301126130b657600080fd5b81516130c96130c482614485565b614454565b915081818352602084019350602081019050838560208402820111156130ee57600080fd5b60005b8381101561311e57816131048882613090565b8452602084019350602083019250506001810190506130f1565b5050505092915050565b60008151905061313781614647565b92915050565b60008135905061314c8161465e565b92915050565b6000813590506131618161466e565b92915050565b6000815190506131768161466e565b92915050565b60006020828403121561318e57600080fd5b600061319c8482850161307b565b91505092915050565b6000602082840312156131b757600080fd5b60006131c584828501613090565b91505092915050565b60008060008060008060008060008060006101608c8e0312156131f057600080fd5b60006131fe8e828f0161307b565b9b5050602061320f8e828f0161307b565b9a505060406132208e828f0161307b565b99505060606132318e828f0161307b565b98505060806132428e828f01613152565b97505060a06132538e828f01613152565b96505060c06132648e828f01613152565b95505060e06132758e828f01613152565b9450506101006132878e828f01613152565b9350506101206132998e828f01613152565b9250506101406132ab8e828f0161313d565b9150509295989b509295989b9093969950565b6000602082840312156132d057600080fd5b600082015167ffffffffffffffff8111156132ea57600080fd5b6132f6848285016130a5565b91505092915050565b60006020828403121561331157600080fd5b600061331f84828501613128565b91505092915050565b60006020828403121561333a57600080fd5b600061334884828501613152565b91505092915050565b60006020828403121561336357600080fd5b600061337184828501613167565b91505092915050565b613383816144e3565b82525050565b613392816144f5565b82525050565b6133a181614501565b82525050565b60006133b2826144b1565b6133bc81856144c7565b93506133cc8185602086016145d6565b80840191505092915050565b6133e18161456a565b82525050565b6133f08161458e565b82525050565b6133ff816145b2565b82525050565b61340e816145c4565b82525050565b600061341f826144bc565b61342981856144d2565b93506134398185602086016145d6565b6134428161460b565b840191505092915050565b600061345a6008836144d2565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b600061349a601b836144d2565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b60006134da6022836144d2565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135406015836144d2565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b6000613580601e836144d2565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006135c06026836144d2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613626601b836144d2565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000613666601c836144d2565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006136a66014836144d2565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006136e6601f836144d2565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613726601e836144d2565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006137666026836144d2565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cc601d836144d2565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b600061380c601a836144d2565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b600061384c6011836144d2565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b600061388c6013836144d2565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b60006138cc601a836144d2565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b600061390c6015836144d2565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b600061394c6029836144d2565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b60006139b2601f836144d2565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b60006139f26021836144d2565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a586020836144d2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613a986016836144d2565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613ad86015836144d2565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613b18601d836144d2565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613b586024836144d2565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bbe6013836144d2565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613bfe6019836144d2565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613c3e6017836144d2565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613c7e6005836144d2565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613cbe602a836144d2565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d24602a836144d2565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d8a601e836144d2565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b6000613dca6014836144d2565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613e0a601a836144d2565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000613e4a600f836144d2565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b613e8681614560565b82525050565b6000613e9882846133a7565b915081905092915050565b6000602082019050613eb8600083018461337a565b92915050565b6000604082019050613ed3600083018561337a565b613ee06020830184613405565b9392505050565b6000604082019050613efc600083018561337a565b613f096020830184613e7d565b9392505050565b6000602082019050613f256000830184613389565b92915050565b6000602082019050613f406000830184613398565b92915050565b6000602082019050613f5b60008301846133d8565b92915050565b6000602082019050613f7660008301846133e7565b92915050565b6000602082019050613f9160008301846133f6565b92915050565b60006020820190508181036000830152613fb18184613414565b905092915050565b60006020820190508181036000830152613fd28161344d565b9050919050565b60006020820190508181036000830152613ff28161348d565b9050919050565b60006020820190508181036000830152614012816134cd565b9050919050565b6000602082019050818103600083015261403281613533565b9050919050565b6000602082019050818103600083015261405281613573565b9050919050565b60006020820190508181036000830152614072816135b3565b9050919050565b6000602082019050818103600083015261409281613619565b9050919050565b600060208201905081810360008301526140b281613659565b9050919050565b600060208201905081810360008301526140d281613699565b9050919050565b600060208201905081810360008301526140f2816136d9565b9050919050565b6000602082019050818103600083015261411281613719565b9050919050565b6000602082019050818103600083015261413281613759565b9050919050565b60006020820190508181036000830152614152816137bf565b9050919050565b60006020820190508181036000830152614172816137ff565b9050919050565b600060208201905081810360008301526141928161383f565b9050919050565b600060208201905081810360008301526141b28161387f565b9050919050565b600060208201905081810360008301526141d2816138bf565b9050919050565b600060208201905081810360008301526141f2816138ff565b9050919050565b600060208201905081810360008301526142128161393f565b9050919050565b60006020820190508181036000830152614232816139a5565b9050919050565b60006020820190508181036000830152614252816139e5565b9050919050565b6000602082019050818103600083015261427281613a4b565b9050919050565b6000602082019050818103600083015261429281613a8b565b9050919050565b600060208201905081810360008301526142b281613acb565b9050919050565b600060208201905081810360008301526142d281613b0b565b9050919050565b600060208201905081810360008301526142f281613b4b565b9050919050565b6000602082019050818103600083015261431281613bb1565b9050919050565b6000602082019050818103600083015261433281613bf1565b9050919050565b6000602082019050818103600083015261435281613c31565b9050919050565b6000602082019050818103600083015261437281613c71565b9050919050565b6000602082019050818103600083015261439281613cb1565b9050919050565b600060208201905081810360008301526143b281613d17565b9050919050565b600060208201905081810360008301526143d281613d7d565b9050919050565b600060208201905081810360008301526143f281613dbd565b9050919050565b6000602082019050818103600083015261441281613dfd565b9050919050565b6000602082019050818103600083015261443281613e3d565b9050919050565b600060208201905061444e6000830184613e7d565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561447b5761447a614609565b5b8060405250919050565b600067ffffffffffffffff8211156144a05761449f614609565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006144ee82614540565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061453b8261461c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006145758261457c565b9050919050565b600061458782614540565b9050919050565b6000614599826145a0565b9050919050565b60006145ab82614540565b9050919050565b60006145bd8261452d565b9050919050565b60006145cf82614560565b9050919050565b60005b838110156145f45780820151818401526020810190506145d9565b83811115614603576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061462d5761462c614609565b5b50565b614639816144e3565b811461464457600080fd5b50565b614650816144f5565b811461465b57600080fd5b50565b6003811061466b57600080fd5b50565b61467781614560565b811461468257600080fd5b5056fea264697066735822122013f3b022e354ddf49f7a28727f309f858a5cbdf70833a2e54da3c1a482b7073164736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610b93578063e8dda6f514610bbc578063e97d87d514610be7578063ebbab99214610c12578063f2fde38b14610c3d578063fc0c546a14610c6657610295565b8063bc0163c114610ac0578063bd896dcb14610aeb578063ce845d1d14610b14578063d0ebdbe714610b3f578063d18e81b314610b6857610295565b806391f7cfb9116100fd57806391f7cfb9146109ff578063a4caeb4214610a2a578063b0d1818c14610a55578063b470aade14610a7e578063b6549f7514610aa957610295565b806386d00e021461095057806386d1a69f1461097b578063872a7810146109925780638a5bdf5c146109bd5780638da5cb5b146109d457610295565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108765780635b940081146108a157806360e79944146108cc578063715018a6146108e357806378e97925146108fa5780637bdf05af1461092557610295565b8063392e53cd1461079f578063398057a3146107ca57806344b1231f146107f557806345d30a1714610820578063481c6a751461084b57610295565b80632a627814116102195780632a627814146106dc5780632bc9ed02146106f35780633197cbb61461071e57806337aeb0861461074957806338af3eed1461077457610295565b8063029c6c9f1461061957806306040618146106445780630b80f7771461066f5780630dff24d5146106865780630fb5a6b4146106b157610295565b36610295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028c90613fb9565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c90614199565b60405180910390fd5b60003414610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035f90613fd9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103e99190613f2b565b60206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043991906131a5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a290614299565b60405180910390fd5b60006104b5610c91565b9050610506826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d43565b506001600281111561051457fe5b603b60009054906101000a900460ff16600281111561052f57fe5b141561061557600061053f610c91565b90508181101561058157600061055e8284610d8d90919063ffffffff16565b905061057581603f54610ddd90919063ffffffff16565b603f81905550506105c7565b60006105968383610d8d90919063ffffffff16565b9050603f548110156105bc576105b781603f54610d8d90919063ffffffff16565b6105bf565b60005b603f81905550505b6105cf610e32565b603f541115610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060a906141f9565b60405180910390fd5b505b5050005b34801561062557600080fd5b5061062e610ea1565b60405161063b9190614439565b60405180910390f35b34801561065057600080fd5b50610659610ebf565b6040516106669190614439565b60405180910390f35b34801561067b57600080fd5b50610684610efa565b005b34801561069257600080fd5b5061069b611067565b6040516106a89190614439565b60405180910390f35b3480156106bd57600080fd5b506106c66110ae565b6040516106d39190614439565b60405180910390f35b3480156106e857600080fd5b506106f16110cc565b005b3480156106ff57600080fd5b50610708611331565b6040516107159190613f10565b60405180910390f35b34801561072a57600080fd5b50610733611344565b6040516107409190614439565b60405180910390f35b34801561075557600080fd5b5061075e61134a565b60405161076b9190614439565b60405180910390f35b34801561078057600080fd5b50610789611350565b6040516107969190613ea3565b60405180910390f35b3480156107ab57600080fd5b506107b4611376565b6040516107c19190613f10565b60405180910390f35b3480156107d657600080fd5b506107df611389565b6040516107ec9190614439565b60405180910390f35b34801561080157600080fd5b5061080a610e32565b6040516108179190614439565b60405180910390f35b34801561082c57600080fd5b5061083561138f565b6040516108429190614439565b60405180910390f35b34801561085757600080fd5b50610860611395565b60405161086d9190613f61565b60405180910390f35b34801561088257600080fd5b5061088b6113bb565b6040516108989190613f10565b60405180910390f35b3480156108ad57600080fd5b506108b66113ce565b6040516108c39190614439565b60405180910390f35b3480156108d857600080fd5b506108e16114d9565b005b3480156108ef57600080fd5b506108f861171f565b005b34801561090657600080fd5b5061090f61186b565b60405161091c9190614439565b60405180910390f35b34801561093157600080fd5b5061093a611871565b6040516109479190614439565b60405180910390f35b34801561095c57600080fd5b506109656118ad565b6040516109729190614439565b60405180910390f35b34801561098757600080fd5b506109906118b3565b005b34801561099e57600080fd5b506109a7611a8f565b6040516109b49190613f7c565b60405180910390f35b3480156109c957600080fd5b506109d2611aa2565b005b3480156109e057600080fd5b506109e9611b7b565b6040516109f69190613ea3565b60405180910390f35b348015610a0b57600080fd5b50610a14611ba4565b604051610a219190614439565b60405180910390f35b348015610a3657600080fd5b50610a3f611c02565b604051610a4c9190614439565b60405180910390f35b348015610a6157600080fd5b50610a7c6004803603810190610a779190613328565b611c08565b005b348015610a8a57600080fd5b50610a93611e07565b604051610aa09190614439565b60405180910390f35b348015610ab557600080fd5b50610abe611e2a565b005b348015610acc57600080fd5b50610ad56120c2565b604051610ae29190614439565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d91906131ce565b6120f4565b005b348015610b2057600080fd5b50610b29610c91565b604051610b369190614439565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061317c565b61211c565b005b348015610b7457600080fd5b50610b7d6121b6565b604051610b8a9190614439565b60405180910390f35b348015610b9f57600080fd5b50610bba6004803603810190610bb5919061317c565b6121be565b005b348015610bc857600080fd5b50610bd1612339565b604051610bde9190614439565b60405180910390f35b348015610bf357600080fd5b50610bfc61233f565b604051610c099190614439565b60405180910390f35b348015610c1e57600080fd5b50610c27612345565b604051610c349190614439565b60405180910390f35b348015610c4957600080fd5b50610c646004803603810190610c5f919061317c565b612367565b005b348015610c7257600080fd5b50610c7b612522565b604051610c889190613f46565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cee9190613ea3565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613351565b905090565b6060610d8583836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b600082821115610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc9906140f9565b60405180910390fd5b818303905092915050565b600080828401905083811015610e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1f90614079565b60405180910390fd5b8091505092915050565b6000600280811115610e4057fe5b603b60009054906101000a900460ff166002811115610e5b57fe5b1415610e6b576035549050610e9e565b6000603a54118015610e855750603a54610e836121b6565b105b15610e935760009050610e9e565b610e9b611ba4565b90505b90565b6000610eba60385460355461256090919063ffffffff16565b905090565b6000610ef56001610ee7610ed1611e07565b610ed9611871565b61256090919063ffffffff16565b610ddd90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7f90614259565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514610fde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fd5906140d9565b60405180910390fd5b611039610fe9611b7b565b610ff1610c91565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611072610c91565b9050600061107e6120c2565b9050808211156110a45761109b8183610d8d90919063ffffffff16565b925050506110ab565b6000925050505b90565b60006110c7603654603754610d8d90919063ffffffff16565b905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461115c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115390614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111c657600080fd5b505afa1580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061120391906132be565b905060005b815181101561130157603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061125b57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b81526004016112a1929190613ee7565b602060405180830381600087803b1580156112bb57600080fd5b505af11580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f391906132ff565b508080600101915050611208565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156113dc57fe5b603b60009054906101000a900460ff1660028111156113f757fe5b141561140c5761140561263c565b90506114d6565b600060395411801561142657506039546114246121b6565b105b1561143457600090506114d6565b6001600281111561144157fe5b603b60009054906101000a900460ff16600281111561145c57fe5b14801561146b57506000603a54115b801561147f5750603a5461147d6121b6565b105b1561148d57600090506114d6565b60006114bf603f546114b1603c546114a3611ba4565b610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b90506114d26114cc610c91565b826126f6565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115d357600080fd5b505afa1580156115e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061161091906132be565b905060005b81518110156116ef57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061166857fe5b602002602001015160006040518363ffffffff1660e01b815260040161168f929190613ebe565b602060405180830381600087803b1580156116a957600080fd5b505af11580156116bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e191906132ff565b508080600101915050611615565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a490614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b60008061187c6121b6565b905060365481116118915760009150506118aa565b6118a660365482610d8d90919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90614359565b60405180910390fd5b600061194d6113ce565b905060008111611992576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611989906143b9565b60405180910390fd5b6119a781603c54610ddd90919063ffffffff16565b603c81905550611a1c603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611a849190614439565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2990614359565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611baf6121b6565b9050603654811015611bc5576000915050611bff565b603754811115611bda57603554915050611bff565b611bfb611be5610ea1565b611bed612345565b61270f90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8f90614359565b60405180910390fd5b60008111611cdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd2906141d9565b60405180910390fd5b80611ce4611067565b1015611d25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1c906142d9565b60405180910390fd5b611d94603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611dfc9190614439565b60405180910390a250565b6000611e25603854611e176110ae565b61256090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90614259565b60405180910390fd5b60016002811115611ec557fe5b603b60009054906101000a900460ff166002811115611ee057fe5b14611f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1790614319565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90614419565b60405180910390fd5b6000611f94611f83610e32565b603554610d8d90919063ffffffff16565b905060008111611fd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd090614099565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061204f612006611b7b565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516120b79190614439565b60405180910390a250565b60006120ef603d546120e1603c54603554610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b905090565b6121068a8a8a8a8a8a8a8a8a8a61277f565b61210f8b612c09565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146121aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a190614259565b60405180910390fd5b6121b381612c09565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461224e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224590614359565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b590614179565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d8160405161232e9190613ea3565b60405180910390a150565b603f5481565b60395481565b60006123626001612354610ebf565b610d8d90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ec90614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245c90614059565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606125578484600085612d87565b90509392505050565b60008082116125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259b90614159565b60405180910390fd5b8183816125ad57fe5b04905092915050565b6126378363a9059cbb60e01b84846040516024016125d5929190613ee7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612e9c565b505050565b60008060395411801561265757506039546126556121b6565b105b1561266557600090506126f3565b6001600281111561267257fe5b603b60009054906101000a900460ff16600281111561268d57fe5b14801561269c57506000603a54115b80156126b05750603a546126ae6121b6565b105b156126be57600090506126f3565b60006126dc603c546126ce611ba4565b610d8d90919063ffffffff16565b90506126ef6126e9610c91565b826126f6565b9150505b90565b60008183106127055781612707565b825b905092915050565b6000808314156127225760009050612779565b600082840290508284828161273357fe5b0414612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90614239565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff16156127cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c6906142f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561283f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612836906140b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128a6906143f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561291f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612916906143d9565b60405180910390fd5b60008711612962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295990614139565b60405180910390fd5b60008614156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299d90614279565b60405180910390fd5b8486106129e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129df90614019565b60405180910390fd5b6001841015612a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2390614219565b60405180910390fd5b60006002811115612a3957fe5b816002811115612a4557fe5b1415612a86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7d90614039565b60405180910390fd5b848310612ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612abf90614379565b60405180910390fd5b848210612b0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0190613ff9565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612b2e8a612f63565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612bf857fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7090614339565b60405180910390fd5b612c8281613001565b612cc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb8906141b9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015612dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dc390614119565b60405180910390fd5b612dd585613001565b612e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0b906142b9565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051612e3e9190613e8c565b60006040518083038185875af1925050503d8060008114612e7b576040519150601f19603f3d011682016040523d82523d6000602084013e612e80565b606091505b5091509150612e90828286613014565b92505050949350505050565b6060612efe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b9050600081511115612f5e5780806020019051810190612f1e91906132ff565b612f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5490614399565b60405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b6060831561302457829050613074565b6000835111156130375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b9190613f97565b60405180910390fd5b9392505050565b60008135905061308a81614630565b92915050565b60008151905061309f81614630565b92915050565b600082601f8301126130b657600080fd5b81516130c96130c482614485565b614454565b915081818352602084019350602081019050838560208402820111156130ee57600080fd5b60005b8381101561311e57816131048882613090565b8452602084019350602083019250506001810190506130f1565b5050505092915050565b60008151905061313781614647565b92915050565b60008135905061314c8161465e565b92915050565b6000813590506131618161466e565b92915050565b6000815190506131768161466e565b92915050565b60006020828403121561318e57600080fd5b600061319c8482850161307b565b91505092915050565b6000602082840312156131b757600080fd5b60006131c584828501613090565b91505092915050565b60008060008060008060008060008060006101608c8e0312156131f057600080fd5b60006131fe8e828f0161307b565b9b5050602061320f8e828f0161307b565b9a505060406132208e828f0161307b565b99505060606132318e828f0161307b565b98505060806132428e828f01613152565b97505060a06132538e828f01613152565b96505060c06132648e828f01613152565b95505060e06132758e828f01613152565b9450506101006132878e828f01613152565b9350506101206132998e828f01613152565b9250506101406132ab8e828f0161313d565b9150509295989b509295989b9093969950565b6000602082840312156132d057600080fd5b600082015167ffffffffffffffff8111156132ea57600080fd5b6132f6848285016130a5565b91505092915050565b60006020828403121561331157600080fd5b600061331f84828501613128565b91505092915050565b60006020828403121561333a57600080fd5b600061334884828501613152565b91505092915050565b60006020828403121561336357600080fd5b600061337184828501613167565b91505092915050565b613383816144e3565b82525050565b613392816144f5565b82525050565b6133a181614501565b82525050565b60006133b2826144b1565b6133bc81856144c7565b93506133cc8185602086016145d6565b80840191505092915050565b6133e18161456a565b82525050565b6133f08161458e565b82525050565b6133ff816145b2565b82525050565b61340e816145c4565b82525050565b600061341f826144bc565b61342981856144d2565b93506134398185602086016145d6565b6134428161460b565b840191505092915050565b600061345a6008836144d2565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b600061349a601b836144d2565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b60006134da6022836144d2565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135406015836144d2565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b6000613580601e836144d2565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006135c06026836144d2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613626601b836144d2565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000613666601c836144d2565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006136a66014836144d2565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006136e6601f836144d2565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613726601e836144d2565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006137666026836144d2565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cc601d836144d2565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b600061380c601a836144d2565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b600061384c6011836144d2565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b600061388c6013836144d2565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b60006138cc601a836144d2565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b600061390c6015836144d2565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b600061394c6029836144d2565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b60006139b2601f836144d2565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b60006139f26021836144d2565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a586020836144d2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613a986016836144d2565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613ad86015836144d2565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613b18601d836144d2565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613b586024836144d2565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bbe6013836144d2565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613bfe6019836144d2565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613c3e6017836144d2565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613c7e6005836144d2565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613cbe602a836144d2565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d24602a836144d2565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d8a601e836144d2565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b6000613dca6014836144d2565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613e0a601a836144d2565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000613e4a600f836144d2565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b613e8681614560565b82525050565b6000613e9882846133a7565b915081905092915050565b6000602082019050613eb8600083018461337a565b92915050565b6000604082019050613ed3600083018561337a565b613ee06020830184613405565b9392505050565b6000604082019050613efc600083018561337a565b613f096020830184613e7d565b9392505050565b6000602082019050613f256000830184613389565b92915050565b6000602082019050613f406000830184613398565b92915050565b6000602082019050613f5b60008301846133d8565b92915050565b6000602082019050613f7660008301846133e7565b92915050565b6000602082019050613f9160008301846133f6565b92915050565b60006020820190508181036000830152613fb18184613414565b905092915050565b60006020820190508181036000830152613fd28161344d565b9050919050565b60006020820190508181036000830152613ff28161348d565b9050919050565b60006020820190508181036000830152614012816134cd565b9050919050565b6000602082019050818103600083015261403281613533565b9050919050565b6000602082019050818103600083015261405281613573565b9050919050565b60006020820190508181036000830152614072816135b3565b9050919050565b6000602082019050818103600083015261409281613619565b9050919050565b600060208201905081810360008301526140b281613659565b9050919050565b600060208201905081810360008301526140d281613699565b9050919050565b600060208201905081810360008301526140f2816136d9565b9050919050565b6000602082019050818103600083015261411281613719565b9050919050565b6000602082019050818103600083015261413281613759565b9050919050565b60006020820190508181036000830152614152816137bf565b9050919050565b60006020820190508181036000830152614172816137ff565b9050919050565b600060208201905081810360008301526141928161383f565b9050919050565b600060208201905081810360008301526141b28161387f565b9050919050565b600060208201905081810360008301526141d2816138bf565b9050919050565b600060208201905081810360008301526141f2816138ff565b9050919050565b600060208201905081810360008301526142128161393f565b9050919050565b60006020820190508181036000830152614232816139a5565b9050919050565b60006020820190508181036000830152614252816139e5565b9050919050565b6000602082019050818103600083015261427281613a4b565b9050919050565b6000602082019050818103600083015261429281613a8b565b9050919050565b600060208201905081810360008301526142b281613acb565b9050919050565b600060208201905081810360008301526142d281613b0b565b9050919050565b600060208201905081810360008301526142f281613b4b565b9050919050565b6000602082019050818103600083015261431281613bb1565b9050919050565b6000602082019050818103600083015261433281613bf1565b9050919050565b6000602082019050818103600083015261435281613c31565b9050919050565b6000602082019050818103600083015261437281613c71565b9050919050565b6000602082019050818103600083015261439281613cb1565b9050919050565b600060208201905081810360008301526143b281613d17565b9050919050565b600060208201905081810360008301526143d281613d7d565b9050919050565b600060208201905081810360008301526143f281613dbd565b9050919050565b6000602082019050818103600083015261441281613dfd565b9050919050565b6000602082019050818103600083015261443281613e3d565b9050919050565b600060208201905061444e6000830184613e7d565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561447b5761447a614609565b5b8060405250919050565b600067ffffffffffffffff8211156144a05761449f614609565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006144ee82614540565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061453b8261461c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006145758261457c565b9050919050565b600061458782614540565b9050919050565b6000614599826145a0565b9050919050565b60006145ab82614540565b9050919050565b60006145bd8261452d565b9050919050565b60006145cf82614560565b9050919050565b60005b838110156145f45780820151818401526020810190506145d9565b83811115614603576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061462d5761462c614609565b5b50565b614639816144e3565b811461464457600080fd5b50565b614650816144f5565b811461465b57600080fd5b50565b6003811061466b57600080fd5b50565b61467781614560565b811461468257600080fd5b5056fea264697066735822122013f3b022e354ddf49f7a28727f309f858a5cbdf70833a2e54da3c1a482b7073164736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6797, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 6802, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 3244, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "51", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 3246, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "52", + "type": "t_address" + }, + { + "astId": 3248, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "53", + "type": "t_uint256" + }, + { + "astId": 3250, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "54", + "type": "t_uint256" + }, + { + "astId": 3252, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "55", + "type": "t_uint256" + }, + { + "astId": 3254, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 3256, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "57", + "type": "t_uint256" + }, + { + "astId": 3258, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "58", + "type": "t_uint256" + }, + { + "astId": 3260, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "59", + "type": "t_enum(Revocability)5096" + }, + { + "astId": 3262, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3264, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3266, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3268, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "60", + "type": "t_uint256" + }, + { + "astId": 3270, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "61", + "type": "t_uint256" + }, + { + "astId": 4692, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "62", + "type": "t_contract(IGraphTokenLockManager)5278" + }, + { + "astId": 4694, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "63", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)5278": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)5096": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Migrations.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Migrations.json new file mode 100644 index 000000000..04fbb9bc1 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Migrations.json @@ -0,0 +1,1083 @@ +{ + "address": "0xec188A659fD9e3CAAD5b14011a18B9F214D54eab", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x50955fbf0ff322d6d02653de2eb1ad23c71c8dfb8a148d2722e6884d7e5d18ae", + "receipt": { + "to": null, + "from": "0xE04FcE05E9B8d21521bd1B0f069982c03BD31F76", + "contractAddress": "0xec188A659fD9e3CAAD5b14011a18B9F214D54eab", + "transactionIndex": 97, + "gasUsed": "3482943", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa33bf934c87da2722bcccab74829772062b90b575ddc86acd3b0b0d00a32f439", + "transactionHash": "0x50955fbf0ff322d6d02653de2eb1ad23c71c8dfb8a148d2722e6884d7e5d18ae", + "logs": [], + "blockNumber": 16477319, + "cumulativeGasUsed": "10861131", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "6f5e8f450f52dd96ebb796aa6620fee9", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n Ownable.initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0x21a1dae4105ba9ff6d9bc38bf983ee853976346562fa284f4b67a3c7ca91a2bf\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n uint256 private constant MAX_UINT256 = 2**256 - 1;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) private {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], MAX_UINT256);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5efc82d408fe81193664e67d614ca6299eafb00163ecc7819fad77cf0d35a2eb\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xc93c7362ac4d74b624b48517985f92c277ce90ae6e5ccb706e70a61af5752077\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613e61806100206000396000f3fe6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 4749, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2578, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "1", + "type": "t_contract(IERC20)1045" + }, + { + "astId": 2580, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 2582, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 2584, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 2586, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 2588, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 2590, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "7", + "type": "t_uint256" + }, + { + "astId": 2592, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 2594, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "9", + "type": "t_enum(Revocability)4426" + }, + { + "astId": 2596, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2598, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2600, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2602, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "10", + "type": "t_uint256" + }, + { + "astId": 2604, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "11", + "type": "t_uint256" + }, + { + "astId": 4021, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "12", + "type": "t_contract(IGraphTokenLockManager)4608" + }, + { + "astId": 4023, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "13", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1045": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)4608": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)4426": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet.json b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet.json new file mode 100644 index 000000000..eb2e70c01 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/GraphTokenLockWallet.json @@ -0,0 +1,1083 @@ +{ + "address": "0xcE18fE70D6331f1Ac403562202B4dc6AC41A10Db", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xbe23d2afa548f1f65b856610ee08dee9d8dc17af9ae4739ddbc1943bd74e7c7e", + "receipt": { + "to": null, + "from": "0xE04FcE05E9B8d21521bd1B0f069982c03BD31F76", + "contractAddress": "0xcE18fE70D6331f1Ac403562202B4dc6AC41A10Db", + "transactionIndex": 114, + "gasUsed": "3482943", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x4cefd91091556f6e808eaea17c8c8a200dce5c8515feaf43c879df3663b73ba5", + "transactionHash": "0xbe23d2afa548f1f65b856610ee08dee9d8dc17af9ae4739ddbc1943bd74e7c7e", + "logs": [], + "blockNumber": 13863234, + "cumulativeGasUsed": "10106601", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "f0757d7c1c560a6ae9697525709a3f5b", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n Ownable.initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0x21a1dae4105ba9ff6d9bc38bf983ee853976346562fa284f4b67a3c7ca91a2bf\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n uint256 private constant MAX_UINT256 = 2**256 - 1;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) private {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], MAX_UINT256);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5efc82d408fe81193664e67d614ca6299eafb00163ecc7819fad77cf0d35a2eb\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xc93c7362ac4d74b624b48517985f92c277ce90ae6e5ccb706e70a61af5752077\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613e61806100206000396000f3fe6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610d0e578063e8dda6f514610d5f578063e97d87d514610d8a578063ebbab99214610db5578063f2fde38b14610de0578063fc0c546a14610e3157610256565b8063bc0163c114610b41578063bd896dcb14610b6c578063ce845d1d14610c67578063d0ebdbe714610c92578063d18e81b314610ce357610256565b806391f7cfb9116100fd57806391f7cfb914610a6e578063a4caeb4214610a99578063b0d1818c14610ac4578063b470aade14610aff578063b6549f7514610b2a57610256565b806386d00e021461099e57806386d1a69f146109c9578063872a7810146109e05780638a5bdf5c14610a165780638da5cb5b14610a2d57610256565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108c25780635b940081146108ef57806360e799441461091a578063715018a61461093157806378e97925146109485780637bdf05af1461097357610256565b8063392e53cd146107d3578063398057a31461080057806344b1231f1461082b57806345d30a1714610856578063481c6a751461088157610256565b80632a627814116102195780632a627814146106f85780632bc9ed021461070f5780633197cbb61461073c57806337aeb0861461076757806338af3eed1461079257610256565b8063029c6c9f1461063557806306040618146106605780630b80f7771461068b5780630dff24d5146106a25780630fb5a6b4146106cd57610256565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610319576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b1580156103d157600080fd5b505afa1580156103e5573d6000803e3d6000fd5b505050506040513d60208110156103fb57600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b60006104bb610e72565b905061050c826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610f3d565b506001600281111561051a57fe5b600960009054906101000a900460ff16600281111561053557fe5b1415610631576000610545610e72565b9050818110156105875760006105648284610f8790919063ffffffff16565b905061057b81600d5461100a90919063ffffffff16565b600d81905550506105cd565b600061059c8383610f8790919063ffffffff16565b9050600d548110156105c2576105bd81600d54610f8790919063ffffffff16565b6105c5565b60005b600d81905550505b6105d5611092565b600d54111561062f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526029815260200180613d346029913960400191505060405180910390fd5b505b5050005b34801561064157600080fd5b5061064a611101565b6040518082815260200191505060405180910390f35b34801561066c57600080fd5b5061067561111f565b6040518082815260200191505060405180910390f35b34801561069757600080fd5b506106a061115a565b005b3480156106ae57600080fd5b506106b761132d565b6040518082815260200191505060405180910390f35b3480156106d957600080fd5b506106e2611374565b6040518082815260200191505060405180910390f35b34801561070457600080fd5b5061070d611392565b005b34801561071b57600080fd5b5061072461165f565b60405180821515815260200191505060405180910390f35b34801561074857600080fd5b50610751611672565b6040518082815260200191505060405180910390f35b34801561077357600080fd5b5061077c611678565b6040518082815260200191505060405180910390f35b34801561079e57600080fd5b506107a761167e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107df57600080fd5b506107e86116a4565b60405180821515815260200191505060405180910390f35b34801561080c57600080fd5b506108156116b7565b6040518082815260200191505060405180910390f35b34801561083757600080fd5b50610840611092565b6040518082815260200191505060405180910390f35b34801561086257600080fd5b5061086b6116bd565b6040518082815260200191505060405180910390f35b34801561088d57600080fd5b506108966116c3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156108ce57600080fd5b506108d76116e9565b60405180821515815260200191505060405180910390f35b3480156108fb57600080fd5b506109046116fc565b6040518082815260200191505060405180910390f35b34801561092657600080fd5b5061092f611807565b005b34801561093d57600080fd5b50610946611ab5565b005b34801561095457600080fd5b5061095d611c34565b6040518082815260200191505060405180910390f35b34801561097f57600080fd5b50610988611c3a565b6040518082815260200191505060405180910390f35b3480156109aa57600080fd5b506109b3611c76565b6040518082815260200191505060405180910390f35b3480156109d557600080fd5b506109de611c7c565b005b3480156109ec57600080fd5b506109f5611ebe565b60405180826002811115610a0557fe5b815260200191505060405180910390f35b348015610a2257600080fd5b50610a2b611ed1565b005b348015610a3957600080fd5b50610a42611fdd565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a7a57600080fd5b50610a83612006565b6040518082815260200191505060405180910390f35b348015610aa557600080fd5b50610aae612064565b6040518082815260200191505060405180910390f35b348015610ad057600080fd5b50610afd60048036036020811015610ae757600080fd5b810190808035906020019092919050505061206a565b005b348015610b0b57600080fd5b50610b146122e5565b6040518082815260200191505060405180910390f35b348015610b3657600080fd5b50610b3f612308565b005b348015610b4d57600080fd5b50610b5661266c565b6040518082815260200191505060405180910390f35b348015610b7857600080fd5b50610c656004803603610160811015610b9057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff16906020019092919050505061269e565b005b348015610c7357600080fd5b50610c7c610e72565b6040518082815260200191505060405180910390f35b348015610c9e57600080fd5b50610ce160048036036020811015610cb557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506126c6565b005b348015610cef57600080fd5b50610cf8612793565b6040518082815260200191505060405180910390f35b348015610d1a57600080fd5b50610d5d60048036036020811015610d3157600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061279b565b005b348015610d6b57600080fd5b50610d74612992565b6040518082815260200191505060405180910390f35b348015610d9657600080fd5b50610d9f612998565b6040518082815260200191505060405180910390f35b348015610dc157600080fd5b50610dca61299e565b6040518082815260200191505060405180910390f35b348015610dec57600080fd5b50610e2f60048036036020811015610e0357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506129c0565b005b348015610e3d57600080fd5b50610e46612bc4565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610efd57600080fd5b505afa158015610f11573d6000803e3d6000fd5b505050506040513d6020811015610f2757600080fd5b8101908080519060200190929190505050905090565b6060610f7f83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612bea565b905092915050565b600082821115610fff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b600080828401905083811015611088576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60006002808111156110a057fe5b600960009054906101000a900460ff1660028111156110bb57fe5b14156110cb5760035490506110fe565b60006008541180156110e557506008546110e3612793565b105b156110f357600090506110fe565b6110fb612006565b90505b90565b600061111a600654600354612c0290919063ffffffff16565b905090565b600061115560016111476111316122e5565b611139611c3a565b612c0290919063ffffffff16565b61100a90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461121b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60001515600960039054906101000a900460ff161515146112a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f43616e6e6f742063616e63656c20616363657074656420636f6e74726163740081525060200191505060405180910390fd5b6112ff6112af611fdd565b6112b7610e72565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611338610e72565b9050600061134461266c565b90508082111561136a576113618183610f8790919063ffffffff16565b92505050611371565b6000925050505b90565b600061138d600454600554610f8790919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611455576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156114bf57600080fd5b505afa1580156114d3573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156114fd57600080fd5b810190808051604051939291908464010000000082111561151d57600080fd5b8382019150602082018581111561153357600080fd5b825186602082028301116401000000008211171561155057600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561158757808201518184015260208101905061156c565b50505050905001604052505050905060005b815181101561162f576116228282815181106115b157fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611599565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600b5481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960039054906101000a900460ff1681565b600060028081111561170a57fe5b600960009054906101000a900460ff16600281111561172557fe5b141561173a57611733612ef2565b9050611804565b60006007541180156117545750600754611752612793565b105b156117625760009050611804565b6001600281111561176f57fe5b600960009054906101000a900460ff16600281111561178a57fe5b14801561179957506000600854115b80156117ad57506008546117ab612793565b105b156117bb5760009050611804565b60006117ed600d546117df600a546117d1612006565b610f8790919063ffffffff16565b610f8790919063ffffffff16565b90506118006117fa610e72565b82612fac565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b15801561193457600080fd5b505afa158015611948573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f82011682018060405250602081101561197257600080fd5b810190808051604051939291908464010000000082111561199257600080fd5b838201915060208201858111156119a857600080fd5b82518660208202830111640100000000821117156119c557600080fd5b8083526020830192505050908051906020019060200280838360005b838110156119fc5780820151818401526020810190506119e1565b50505050905001604052505050905060005b8151811015611a8557611a78828281518110611a2657fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612d2d9092919063ffffffff16565b8080600101915050611a0e565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611b76576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b600080611c45612793565b90506004548111611c5a576000915050611c73565b611c6f60045482610f8790919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611d3f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6000611d496116fc565b905060008111611dc1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611dd681600a5461100a90919063ffffffff16565b600a81905550611e4b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611f94576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6001600960036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080612011612793565b9050600454811015612027576000915050612061565b60055481111561203c57600354915050612061565b61205d612047611101565b61204f61299e565b612fc590919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461212d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600081116121a3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b806121ac61132d565b1015612203576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613d7e6024913960400191505060405180910390fd5b612272600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b60006123036006546122f5611374565b612c0290919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600160028111156123d657fe5b600960009054906101000a900460ff1660028111156123f157fe5b14612464576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff161515146124ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061250b6124fa611092565b600354610f8790919063ffffffff16565b905060008111612583576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b80600b819055506001600960016101000a81548160ff0219169083151502179055506125f96125b0611fdd565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16612c8b9092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b6000612699600b5461268b600a54600354610f8790919063ffffffff16565b610f8790919063ffffffff16565b905090565b6126b08a8a8a8a8a8a8a8a8a8a61304b565b6126b98b6136cc565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612787576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b612790816136cc565b50565b600042905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461285e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612901576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260118152602001807f456d7074792062656e656669636961727900000000000000000000000000000081525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d81604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b600d5481565b60075481565b60006129bb60016129ad61111f565b610f8790919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614612a81576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612b07576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ce86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6060612bf984846000856138b0565b90509392505050565b6000808211612c79576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525060200191505060405180910390fd5b818381612c8257fe5b04905092915050565b612d288363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b6000811480612dfb575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b158015612dbe57600080fd5b505afa158015612dd2573d6000803e3d6000fd5b505050506040513d6020811015612de857600080fd5b8101908080519060200190929190505050145b612e50576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526036815260200180613df66036913960400191505060405180910390fd5b612eed8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613a59565b505050565b600080600754118015612f0d5750600754612f0b612793565b105b15612f1b5760009050612fa9565b60016002811115612f2857fe5b600960009054906101000a900460ff166002811115612f4357fe5b148015612f5257506000600854115b8015612f665750600854612f64612793565b105b15612f745760009050612fa9565b6000612f92600a54612f84612006565b610f8790919063ffffffff16565b9050612fa5612f9f610e72565b82612fac565b9150505b90565b6000818310612fbb5781612fbd565b825b905092915050565b600080831415612fd85760009050613045565b6000828402905082848281612fe957fe5b0414613040576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613d5d6021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156130ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415613171576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415613214576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff1614156132b7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b6000871161332d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b60008614156133a4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610613419576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015613490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b6000600281111561349d57fe5b8160028111156134a957fe5b141561351d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310613575576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613da2602a913960400191505060405180910390fd5b8482106135cd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613cc66022913960400191505060405180910390fd5b6001600960026101000a81548160ff0219169083151502179055506135f18a613b48565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff021916908360028111156136bb57fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561376f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61377881613be6565b6137ea576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600c60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600c60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b60608247101561390b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613d0e6026913960400191505060405180910390fd5b61391485613be6565b613986576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106139d657805182526020820191506020810190506020830392506139b3565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613a38576040519150601f19603f3d011682016040523d82523d6000602084013e613a3d565b606091505b5091509150613a4d828286613bf9565b92505050949350505050565b6060613abb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16612bea9092919063ffffffff16565b9050600081511115613b4357808060200190516020811015613adc57600080fd5b8101908080519060200190929190505050613b42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613dcc602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b60608315613c0957829050613cbe565b600083511115613c1c5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613c83578082015181840152602081019050613c68565b50505050905090810190601f168015613cb05780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a26469706673582212203c6b20b5a223b9b9c9f0008dfba22c9fb703c6524c0f0a76a2b156733f6d573464736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2339, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 965, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "1", + "type": "t_contract(IERC20)432" + }, + { + "astId": 967, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 969, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 971, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 973, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 975, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 977, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "7", + "type": "t_uint256" + }, + { + "astId": 979, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 981, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "9", + "type": "t_enum(Revocability)2132" + }, + { + "astId": 983, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 985, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 987, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 989, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "10", + "type": "t_uint256" + }, + { + "astId": 991, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "11", + "type": "t_uint256" + }, + { + "astId": 1755, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "12", + "type": "t_contract(IGraphTokenLockManager)2314" + }, + { + "astId": 1757, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "13", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)432": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)2314": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)2132": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/L1GraphTokenLockTransferTool.json b/packages/token-distribution/deployments/mainnet/L1GraphTokenLockTransferTool.json new file mode 100644 index 000000000..f25fd6324 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/L1GraphTokenLockTransferTool.json @@ -0,0 +1,612 @@ +{ + "address": "0xCa82c7Ce3388b0B5d307574099aC57d7a00d509F", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Implementation", + "type": "address" + }, + { + "internalType": "contract ITokenGateway", + "name": "_l1Gateway", + "type": "address" + }, + { + "internalType": "address payable", + "name": "_staking", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHPulled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Beneficiary", + "type": "address" + } + ], + "name": "L2BeneficiarySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1LockManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + } + ], + "name": "L2LockManagerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + } + ], + "name": "L2WalletAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1WalletOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2WalletOwner", + "type": "address" + } + ], + "name": "L2WalletOwnerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedFundsSentToL2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenLock", + "type": "address" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_l2Beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSubmissionCost", + "type": "uint256" + } + ], + "name": "depositToL2Locked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "graphToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Gateway", + "outputs": [ + { + "internalType": "contract ITokenGateway", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2Beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2LockManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletAddressSetManually", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenLock", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "pullETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1LockManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2LockManager", + "type": "address" + } + ], + "name": "setL2LockManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Wallet", + "type": "address" + } + ], + "name": "setL2WalletAddressManually", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1WalletOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WalletOwner", + "type": "address" + } + ], + "name": "setL2WalletOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "staking", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenLockETHBalances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_destination", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x8535f77828c04d09f10107dea149d9ad72b477a386fd482d109d456e487667e0" +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/solcInputs/5ad03e035f8e3c63878532d87a315ef8.json b/packages/token-distribution/deployments/mainnet/solcInputs/5ad03e035f8e3c63878532d87a315ef8.json new file mode 100644 index 000000000..f7d8663a5 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/solcInputs/5ad03e035f8e3c63878532d87a315ef8.json @@ -0,0 +1,83 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) private {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], MAX_UINT256);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n Ownable.initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 private _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSignature(\n \"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\",\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\n external\n override\n onlyOwner\n {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\n\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n// Based on https://eips.ethereum.org/EIPS/eip-1167\ncontract MinimalProxyFactory is Ownable {\n // -- Events --\n\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\n }\n\n /**\n * @notice Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(\n bytes32 _salt,\n address _implementation,\n bytes memory _data\n ) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @notice Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n * \n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n Ownable.initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/solcInputs/6f5e8f450f52dd96ebb796aa6620fee9.json b/packages/token-distribution/deployments/mainnet/solcInputs/6f5e8f450f52dd96ebb796aa6620fee9.json new file mode 100644 index 000000000..fafe342a8 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/solcInputs/6f5e8f450f52dd96ebb796aa6620fee9.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) private {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], MAX_UINT256);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n Ownable.initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/StakingMock.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/Stakes.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(\n Stakes.Indexer storage stake,\n uint256 _tokens,\n uint256 _period\n ) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(Stakes.Indexer memory stake, uint256 _delegatedCapacity)\n internal\n pure\n returns (uint256)\n {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "contracts/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @dev Contract Constructor.\n * @param _initialSupply Initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\n\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n// Based on https://eips.ethereum.org/EIPS/eip-1167\ncontract MinimalProxyFactory is Ownable {\n // -- Events --\n\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\n }\n\n /**\n * @notice Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(\n bytes32 _salt,\n address _implementation,\n bytes memory _data\n ) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @notice Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 private _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSignature(\n \"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\",\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\n external\n override\n onlyOwner\n {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n *\n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n Ownable.initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json b/packages/token-distribution/deployments/mainnet/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json new file mode 100644 index 000000000..ee7330e86 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../GSN/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction overflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/GSN/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) private {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], MAX_UINT256);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n uint256 public releasedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n Ownable.initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public override view returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public override view returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public override view returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public override view returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public override view returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public override view returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public override view returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public override view returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public override view returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public override view returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public override view returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public override view returns (uint256) {\n return managedAmount.sub(releasedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public override view returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability { NotSet, Enabled, Disabled }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/StakingMock.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/Stakes.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(\n Stakes.Indexer storage stake,\n uint256 _tokens,\n uint256 _period\n ) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(Stakes.Indexer memory stake, uint256 _delegatedCapacity)\n internal\n pure\n returns (uint256)\n {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "contracts/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @dev Contract Constructor.\n * @param _initialSupply Initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\n\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n// Based on https://eips.ethereum.org/EIPS/eip-1167\ncontract MinimalProxyFactory is Ownable {\n // -- Events --\n\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\n }\n\n /**\n * @notice Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(\n bytes32 _salt,\n address _implementation,\n bytes memory _data\n ) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @notice Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint256(_data));\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 private _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSignature(\n \"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\",\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\n external\n override\n onlyOwner\n {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint256(_at(set._inner, index)));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n * \n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n Ownable.initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json b/packages/token-distribution/deployments/mainnet/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json new file mode 100644 index 000000000..4eda754ae --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json @@ -0,0 +1,152 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMathUpgradeable {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/arbitrum/ITokenGateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2020, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\ninterface ITokenGateway {\n /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated\n // event OutboundTransferInitiated(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized\n // event InboundTransferFinalized(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n function outboundTransfer(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n function finalizeInboundTransfer(\n address _token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n\n /**\n * @notice Calculate the address used when bridging an ERC20 token\n * @dev the L1 and L2 address oracles may not always be in sync.\n * For example, a custom token may have been registered but not deployed or the contract self destructed.\n * @param l1ERC20 address of L1 token\n * @return L2 address of a bridged ERC20 token\n */\n function calculateL2TokenAddress(address l1ERC20) external view returns (address);\n}\n" + }, + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n OwnableInitializable._initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 internal _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSelector(\n GraphTokenLockWallet.initialize.selector,\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(\n string[] calldata _signatures,\n address[] calldata _targets\n ) external override onlyOwner {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n *\n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n OwnableInitializable._initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) internal {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe because we are using the max uint256 value\n token.approve(dstList[i], type(uint256).max);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe cause we're using 0 as the amount\n token.approve(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n require(msg.value == 0, \"ETH transfers not supported\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n\n /**\n * @notice Receive function that always reverts.\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\n */\n receive() external payable {\n revert(\"Bad call\");\n }\n}\n" + }, + "contracts/ICallhookReceiver.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\n\n/**\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\n * be allowlisted by the governor, but also implement this interface that contains\n * the function that will actually be called by the L2GraphTokenGateway.\n */\npragma solidity ^0.7.3;\n\ninterface ICallhookReceiver {\n /**\n * @notice Receive tokens with a callhook from the bridge\n * @param _from Token sender in L1\n * @param _amount Amount of tokens that were transferred\n * @param _data ABI-encoded callhook data\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/L1GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { AddressUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { MinimalProxyFactory } from \"./MinimalProxyFactory.sol\";\nimport { IGraphTokenLock } from \"./IGraphTokenLock.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { SafeMathUpgradeable } from \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @title L1GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from GraphTokenLockWallets\n * to a counterpart on L2. It is deployed on L1 and will send the GRT through\n * the L1GraphTokenGateway with a callhook to the L2GraphTokenLockManager, including\n * data to create a L2GraphTokenLockWallet on L2.\n *\n * Note that the L2GraphTokenLockWallet will not allow releasing any GRT until the end of\n * the vesting timeline, but will allow sending the GRT back to the L1 wallet.\n *\n * Beneficiaries for a GraphTokenLockWallet can perform the depositToL2Locked call\n * as many times as they want, and the GRT will be sent to the same L2GraphTokenLockWallet.\n *\n * Since all retryable tickets to send transactions to L2 require ETH for gas, this\n * contract also allows users to deposit ETH to be used for gas on L2, both for\n * the depositToL2Locked calls and for the transfer tools in the Staking contract for\n * The Graph.\n *\n * See GIP-0046 for more details: https://forum.thegraph.com/t/4023\n */\ncontract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, MinimalProxyFactory {\n using SafeMathUpgradeable for uint256;\n\n /// Address of the L1 GRT token contract\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses\n address public immutable l2Implementation;\n /// Address of the L1GraphTokenGateway contract\n ITokenGateway public immutable l1Gateway;\n /// Address of the Staking contract, used to pull ETH for L2 ticket gas\n address payable public immutable staking;\n /// L2 lock manager for each L1 lock manager.\n /// L1 GraphTokenLockManager => L2GraphTokenLockManager\n mapping(address => address) public l2LockManager;\n /// L2 wallet owner for each L1 wallet owner.\n /// L1 wallet owner => L2 wallet owner\n mapping(address => address) public l2WalletOwner;\n /// L2 wallet address for each L1 wallet address.\n /// L1 wallet => L2 wallet\n mapping(address => address) public l2WalletAddress;\n /// ETH balance from each token lock, used to pay for L2 gas:\n /// L1 wallet address => ETH balance\n mapping(address => uint256) public tokenLockETHBalances;\n /// L2 beneficiary corresponding to each L1 wallet address.\n /// L1 wallet => L2 beneficiary\n mapping(address => address) public l2Beneficiary;\n /// Indicates whether an L2 wallet address for a wallet\n /// has been set manually, in which case it can't call depositToL2Locked.\n /// L1 wallet => bool\n mapping(address => bool) public l2WalletAddressSetManually;\n\n /// @dev Emitted when the L2 lock manager for an L1 lock manager is set\n event L2LockManagerSet(address indexed l1LockManager, address indexed l2LockManager);\n /// @dev Emitted when the L2 wallet owner for an L1 wallet owner is set\n event L2WalletOwnerSet(address indexed l1WalletOwner, address indexed l2WalletOwner);\n /// @dev Emitted when GRT is sent to L2 from a token lock\n event LockedFundsSentToL2(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l1LockManager,\n address l2LockManager,\n uint256 amount\n );\n /// @dev Emitted when an L2 wallet address is set for an L1 wallet\n event L2WalletAddressSet(address indexed l1Wallet, address indexed l2Wallet);\n /// @dev Emitted when ETH is deposited to a token lock's account\n event ETHDeposited(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when ETH is withdrawn from a token lock's account\n event ETHWithdrawn(address indexed tokenLock, address indexed destination, uint256 amount);\n /// @dev Emitted when ETH is pulled from a token lock's account by Staking or this tool to pay for an L2 ticket\n event ETHPulled(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when the L2 beneficiary for a partially vested L1 lock is set\n event L2BeneficiarySet(address indexed l1Wallet, address indexed l2Beneficiary);\n\n /**\n * @notice Construct a new L1GraphTokenLockTransferTool contract\n * @dev The deployer of the contract will become its owner.\n * Note this contract is meant to be deployed behind a transparent proxy,\n * so this will run at the implementation's storage context; it will set\n * immutable variables and make the implementation be owned by the deployer.\n * @param _graphToken Address of the L1 GRT token contract\n * @param _l2Implementation Address of the L2GraphTokenLockWallet implementation in L2\n * @param _l1Gateway Address of the L1GraphTokenGateway contract\n * @param _staking Address of the Staking contract\n */\n constructor(\n IERC20 _graphToken,\n address _l2Implementation,\n ITokenGateway _l1Gateway,\n address payable _staking\n ) initializer {\n OwnableInitializable._initialize(msg.sender);\n graphToken = _graphToken;\n l2Implementation = _l2Implementation;\n l1Gateway = _l1Gateway;\n staking = _staking;\n }\n\n /**\n * @notice Initialize the L1GraphTokenLockTransferTool contract\n * @dev This function will run in the proxy's storage context, so it will\n * set the owner of the proxy contract which can be different from the implementation owner.\n * @param _owner Address of the owner of the L1GraphTokenLockTransferTool contract\n */\n function initialize(address _owner) external initializer {\n OwnableInitializable._initialize(_owner);\n }\n\n /**\n * @notice Set the L2 lock manager that corresponds to an L1 lock manager\n * @param _l1LockManager Address of the L1 lock manager\n * @param _l2LockManager Address of the L2 lock manager (in L2)\n */\n function setL2LockManager(address _l1LockManager, address _l2LockManager) external onlyOwner {\n l2LockManager[_l1LockManager] = _l2LockManager;\n emit L2LockManagerSet(_l1LockManager, _l2LockManager);\n }\n\n /**\n * @notice Set the L2 wallet owner that corresponds to an L1 wallet owner\n * @param _l1WalletOwner Address of the L1 wallet owner\n * @param _l2WalletOwner Address of the L2 wallet owner (in L2)\n */\n function setL2WalletOwner(address _l1WalletOwner, address _l2WalletOwner) external onlyOwner {\n l2WalletOwner[_l1WalletOwner] = _l2WalletOwner;\n emit L2WalletOwnerSet(_l1WalletOwner, _l2WalletOwner);\n }\n\n /**\n * @notice Deposit ETH on a token lock's account, to be used for L2 retryable ticket gas.\n * This function can be called by anyone, but the ETH will be credited to the token lock.\n * DO NOT try to call this through the token lock, as locks do not forward ETH value (and the\n * function call should not be allowlisted).\n * @param _tokenLock Address of the L1 GraphTokenLockWallet that will own the ETH\n */\n function depositETH(address _tokenLock) external payable {\n tokenLockETHBalances[_tokenLock] = tokenLockETHBalances[_tokenLock].add(msg.value);\n emit ETHDeposited(_tokenLock, msg.value);\n }\n\n /**\n * @notice Withdraw ETH from a token lock's account.\n * This function must be called from the token lock contract, but the destination\n * _must_ be a different address, as any ETH sent to the token lock would otherwise be\n * lost.\n * @param _destination Address to send the ETH\n * @param _amount Amount of ETH to send\n */\n function withdrawETH(address _destination, uint256 _amount) external {\n require(_amount > 0, \"INVALID_AMOUNT\");\n // We can't send eth to a token lock or it will be stuck\n require(msg.sender != _destination, \"INVALID_DESTINATION\");\n require(tokenLockETHBalances[msg.sender] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[msg.sender] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = payable(_destination).call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHWithdrawn(msg.sender, _destination, _amount);\n }\n\n /**\n * @notice Pull ETH from a token lock's account, to be used for L2 retryable ticket gas.\n * This can only be called by the Staking contract.\n * @param _tokenLock GraphTokenLockWallet that owns the ETH that will be debited\n * @param _amount Amount of ETH to pull\n */\n function pullETH(address _tokenLock, uint256 _amount) external {\n require(msg.sender == staking, \"ONLY_STAKING\");\n require(tokenLockETHBalances[_tokenLock] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[_tokenLock] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = staking.call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHPulled(_tokenLock, _amount);\n }\n\n /**\n * @notice Deposit GRT to L2, from a token lock in L1 to a token lock in L2.\n * If the token lock in L2 does not exist, it will be created when the message is received\n * by the L2GraphTokenLockManager.\n * Before calling this (which must be done through the token lock wallet), make sure\n * there is enough ETH in the token lock's account to cover the L2 retryable ticket gas.\n * Note that L2 submission fee and gas refunds will be lost.\n * You can add ETH to the token lock's account by calling depositETH().\n * Note that after calling this, you will NOT be able to use setL2WalletAddressManually() to\n * set an L2 wallet address, as the L2 wallet address will be set automatically when the\n * message is received by the L2GraphTokenLockManager.\n * @dev The gas parameters for L2 can be estimated using the Arbitrum SDK.\n * @param _amount Amount of GRT to deposit\n * @param _l2Beneficiary Address of the beneficiary for the token lock in L2. Must be the same for subsequent calls of this function, and not an L1 contract.\n * @param _maxGas Maximum gas to use for the L2 retryable ticket\n * @param _gasPriceBid Gas price to use for the L2 retryable ticket\n * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket\n */\n function depositToL2Locked(\n uint256 _amount,\n address _l2Beneficiary,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n uint256 _maxSubmissionCost\n ) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n require(wallet.revocable() != IGraphTokenLock.Revocability.Enabled, \"REVOCABLE\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n if (l2Beneficiary[msg.sender] == address(0)) {\n require(_l2Beneficiary != address(0), \"INVALID_BENEFICIARY_ZERO\");\n require(!AddressUpgradeable.isContract(_l2Beneficiary), \"INVALID_BENEFICIARY_CONTRACT\");\n l2Beneficiary[msg.sender] = _l2Beneficiary;\n emit L2BeneficiarySet(msg.sender, _l2Beneficiary);\n } else {\n require(l2Beneficiary[msg.sender] == _l2Beneficiary, \"INVALID_BENEFICIARY\");\n }\n\n uint256 expectedEth = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(tokenLockETHBalances[msg.sender] >= expectedEth, \"INSUFFICIENT_ETH_BALANCE\");\n tokenLockETHBalances[msg.sender] -= expectedEth;\n\n bytes memory encodedData;\n {\n address l2Owner = l2WalletOwner[wallet.owner()];\n require(l2Owner != address(0), \"L2_OWNER_NOT_SET\");\n // Extract all the storage variables from the GraphTokenLockWallet\n L2GraphTokenLockManager.TransferredWalletData memory data = L2GraphTokenLockManager.TransferredWalletData({\n l1Address: msg.sender,\n owner: l2Owner,\n beneficiary: l2Beneficiary[msg.sender],\n managedAmount: wallet.managedAmount(),\n startTime: wallet.startTime(),\n endTime: wallet.endTime()\n });\n encodedData = abi.encode(data);\n }\n\n if (l2WalletAddress[msg.sender] == address(0)) {\n require(wallet.endTime() >= block.timestamp, \"FULLY_VESTED_USE_MANUAL_ADDRESS\");\n address newAddress = getDeploymentAddress(keccak256(encodedData), l2Implementation, l2Manager);\n l2WalletAddress[msg.sender] = newAddress;\n emit L2WalletAddressSet(msg.sender, newAddress);\n } else {\n require(!l2WalletAddressSetManually[msg.sender], \"CANT_DEPOSIT_TO_MANUAL_ADDRESS\");\n }\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n\n // Send the tokens with a message through the L1GraphTokenGateway to the L2GraphTokenLockManager\n graphToken.approve(address(l1Gateway), _amount);\n {\n bytes memory transferData = abi.encode(_maxSubmissionCost, encodedData);\n l1Gateway.outboundTransfer{ value: expectedEth }(\n address(graphToken),\n l2Manager,\n _amount,\n _maxGas,\n _gasPriceBid,\n transferData\n );\n }\n emit ETHPulled(msg.sender, expectedEth);\n emit LockedFundsSentToL2(msg.sender, l2WalletAddress[msg.sender], l1Manager, l2Manager, _amount);\n }\n\n /**\n * @notice Manually set the L2 wallet address for a token lock in L1.\n * This will only work for token locks that have not been initialized in L2 yet, and\n * that are fully vested (endTime < current timestamp).\n * This address can then be used to send stake or delegation to L2 on the Staking contract.\n * After calling this, the vesting lock will NOT be allowed to use depositToL2Locked\n * to send GRT to L2, the beneficiary must withdraw the tokens and bridge them manually.\n * @param _l2Wallet Address of the L2 wallet\n */\n function setL2WalletAddressManually(address _l2Wallet) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n\n // Check that the wallet is fully vested\n require(wallet.endTime() < block.timestamp, \"NOT_FULLY_VESTED\");\n\n // Check that the wallet has not set an L2 wallet yet\n require(l2WalletAddress[msg.sender] == address(0), \"L2_WALLET_ALREADY_SET\");\n\n // Check that the L2 address is not zero\n require(_l2Wallet != address(0), \"ZERO_ADDRESS\");\n // Set the L2 wallet address\n l2WalletAddress[msg.sender] = _l2Wallet;\n l2WalletAddressSetManually[msg.sender] = true;\n emit L2WalletAddressSet(msg.sender, _l2Wallet);\n }\n}\n" + }, + "contracts/L2GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { ICallhookReceiver } from \"./ICallhookReceiver.sol\";\nimport { GraphTokenLockManager } from \"./GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\n\n/**\n * @title L2GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\n * the L2GraphTokenLockTransferTool contract.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\n using SafeERC20 for IERC20;\n\n /// @dev Struct to hold the data of a transferred wallet; this is\n /// the data that must be encoded in L1 to send a wallet to L2.\n struct TransferredWalletData {\n address l1Address;\n address owner;\n address beneficiary;\n uint256 managedAmount;\n uint256 startTime;\n uint256 endTime;\n }\n\n /// Address of the L2GraphTokenGateway\n address public immutable l2Gateway;\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\n address public immutable l1TransferTool;\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\n /// L1 address => L2 address\n mapping(address => address) public l1WalletToL2Wallet;\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\n /// L2 address => L1 address\n mapping(address => address) public l2WalletToL1Wallet;\n\n /// @dev Event emitted when a wallet is received and created from L1\n event TokenLockCreatedFromL1(\n address indexed contractAddress,\n bytes32 initHash,\n address indexed beneficiary,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n address indexed l1Address\n );\n\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\n /// had already been received or not)\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\n\n /**\n * @dev Checks that the sender is the L2GraphTokenGateway.\n */\n modifier onlyL2Gateway() {\n require(msg.sender == l2Gateway, \"ONLY_GATEWAY\");\n _;\n }\n\n /**\n * @notice Constructor for the L2GraphTokenLockManager contract.\n * @param _graphToken Address of the L2 GRT token contract\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\n */\n constructor(\n IERC20 _graphToken,\n address _masterCopy,\n address _l2Gateway,\n address _l1TransferTool\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\n l2Gateway = _l2Gateway;\n l1TransferTool = _l1TransferTool;\n }\n\n /**\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\n * the existing wallet if it does.\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\n * @param _amount Amount of tokens received\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\n require(_from == l1TransferTool, \"ONLY_TRANSFER_TOOL\");\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\n\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\n // If the wallet was already received, just send the tokens to the L2 address\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\n } else {\n // Create contract using a minimal proxy and call initializer\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _amount);\n\n emit TokenLockCreatedFromL1(\n contractAddress,\n initHash,\n walletData.beneficiary,\n walletData.managedAmount,\n walletData.startTime,\n walletData.endTime,\n walletData.l1Address\n );\n }\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\n }\n\n /**\n * @dev Deploy a token lock wallet with data received from L1\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\n * @param _walletData Data of the wallet to be created\n * @return Hash of the initialization calldata\n * @return Address of the created contract\n */\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\n bytes memory initializer = _encodeInitializer(_walletData);\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\n return (keccak256(initializer), contractAddress);\n }\n\n /**\n * @dev Encode the initializer for the token lock wallet received from L1\n * @param _walletData Data of the wallet to be created\n * @return Encoded initializer calldata, including the function signature\n */\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\n return\n abi.encodeWithSelector(\n L2GraphTokenLockWallet.initializeFromL1.selector,\n address(this),\n address(_token),\n _walletData\n );\n }\n}\n" + }, + "contracts/L2GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\n\n/**\n * @title L2GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from L2 token lock wallets\n * back to their L1 counterparts.\n */\ncontract L2GraphTokenLockTransferTool {\n /// Address of the L2 GRT token\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenGateway\n ITokenGateway public immutable l2Gateway;\n /// Address of the L1 GRT token (in L1, no aliasing)\n address public immutable l1GraphToken;\n\n /// @dev Emitted when GRT is sent to L1 from a token lock\n event LockedFundsSentToL1(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l2LockManager,\n uint256 amount\n );\n\n /**\n * @notice Constructor for the L2GraphTokenLockTransferTool contract\n * @dev Note the L2GraphTokenLockTransferTool can be deployed behind a proxy,\n * and the constructor for the implementation will only set some immutable\n * variables.\n * @param _graphToken Address of the L2 GRT token\n * @param _l2Gateway Address of the L2GraphTokenGateway\n * @param _l1GraphToken Address of the L1 GRT token (in L1, no aliasing)\n */\n constructor(IERC20 _graphToken, ITokenGateway _l2Gateway, address _l1GraphToken) {\n graphToken = _graphToken;\n l2Gateway = _l2Gateway;\n l1GraphToken = _l1GraphToken;\n }\n\n /**\n * @notice Withdraw GRT from an L2 token lock wallet to its L1 counterpart.\n * This function must be called from an L2GraphTokenLockWallet contract.\n * The GRT will be sent to L1 and must be claimed using the Arbitrum Outbox on L1\n * after the standard Arbitrum withdrawal period (7 days).\n * @param _amount Amount of GRT to withdraw\n */\n function withdrawToL1Locked(uint256 _amount) external {\n L2GraphTokenLockWallet wallet = L2GraphTokenLockWallet(msg.sender);\n L2GraphTokenLockManager manager = L2GraphTokenLockManager(address(wallet.manager()));\n require(address(manager) != address(0), \"INVALID_SENDER\");\n address l1Wallet = manager.l2WalletToL1Wallet(msg.sender);\n require(l1Wallet != address(0), \"NOT_L1_WALLET\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n graphToken.approve(address(l2Gateway), _amount);\n\n // Send the tokens through the L2GraphTokenGateway to the L1 wallet counterpart\n l2Gateway.outboundTransfer(l1GraphToken, l1Wallet, _amount, 0, 0, \"\");\n emit LockedFundsSentToL1(l1Wallet, msg.sender, address(manager), _amount);\n }\n}\n" + }, + "contracts/L2GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\n\n/**\n * @title L2GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * This L2 variant includes a special initializer so that it can be created from\n * a wallet's data received from L1. These transferred wallets will not allow releasing\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\n *\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\n // Initializer when created from a message from L1\n function initializeFromL1(\n address _manager,\n address _token,\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\n ) external {\n require(!isInitialized, \"Already initialized\");\n isInitialized = true;\n\n OwnableInitializable._initialize(_walletData.owner);\n beneficiary = _walletData.beneficiary;\n token = IERC20(_token);\n\n managedAmount = _walletData.managedAmount;\n\n startTime = _walletData.startTime;\n endTime = _walletData.endTime;\n periods = 1;\n isAccepted = true;\n\n // Optionals\n releaseStartTime = _walletData.endTime;\n revocable = Revocability.Disabled;\n\n _setManager(_manager);\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { Create2 } from \"@openzeppelin/contracts/utils/Create2.sol\";\n\n/**\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n * Based on https://eips.ethereum.org/EIPS/eip-1167\n */\ncontract MinimalProxyFactory {\n /// @dev Emitted when a new proxy is created\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _deployer Address of the deployer that creates the contract\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation,\n address _deployer\n ) public pure returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\n }\n\n /**\n * @dev Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @dev Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n /// @dev Owner of the contract, can be retrieved with the public owner() function\n address private _owner;\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\n /// to allow adding variables here without breaking the proxy storage layout\n uint256[50] private __gap;\n\n /// @dev Emitted when ownership of the contract is transferred\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function _initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/tests/arbitrum/AddressAliasHelper.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/84e64dee6ee82adbf8ec34fd4b86c207a61d9007/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n l2Address = address(uint160(l1Address) + offset);\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n l1Address = address(uint160(l2Address) - offset);\n }\n}\n" + }, + "contracts/tests/arbitrum/IBridge.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IBridge {\n event MessageDelivered(\n uint256 indexed messageIndex,\n bytes32 indexed beforeInboxAcc,\n address inbox,\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n );\n\n event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);\n\n event InboxToggle(address indexed inbox, bool enabled);\n\n event OutboxToggle(address indexed outbox, bool enabled);\n\n function deliverMessageToInbox(\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n ) external payable returns (uint256);\n\n function executeCall(\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (bool success, bytes memory returnData);\n\n // These are only callable by the admin\n function setInbox(address inbox, bool enabled) external;\n\n function setOutbox(address inbox, bool enabled) external;\n\n // View functions\n\n function activeOutbox() external view returns (address);\n\n function allowedInboxes(address inbox) external view returns (bool);\n\n function allowedOutboxes(address outbox) external view returns (bool);\n\n function inboxAccs(uint256 index) external view returns (bytes32);\n\n function messageCount() external view returns (uint256);\n}\n" + }, + "contracts/tests/arbitrum/IInbox.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nimport \"./IBridge.sol\";\nimport \"./IMessageProvider.sol\";\n\ninterface IInbox is IMessageProvider {\n function sendL2Message(bytes calldata messageData) external returns (uint256);\n\n function sendUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendL1FundedUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function sendL1FundedContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function createRetryableTicket(\n address destAddr,\n uint256 arbTxCallValue,\n uint256 maxSubmissionCost,\n address submissionRefundAddress,\n address valueRefundAddress,\n uint256 maxGas,\n uint256 gasPriceBid,\n bytes calldata data\n ) external payable returns (uint256);\n\n function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);\n\n function bridge() external view returns (IBridge);\n\n function pauseCreateRetryables() external;\n\n function unpauseCreateRetryables() external;\n\n function startRewriteAddress() external;\n\n function stopRewriteAddress() external;\n}\n" + }, + "contracts/tests/arbitrum/IMessageProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IMessageProvider {\n event InboxMessageDelivered(uint256 indexed messageNum, bytes data);\n\n event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);\n}\n" + }, + "contracts/tests/BridgeMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IBridge.sol\";\n\n/**\n * @title Arbitrum Bridge mock contract\n * @dev This contract implements Arbitrum's IBridge interface for testing purposes\n */\ncontract BridgeMock is IBridge {\n /// Address of the (mock) Arbitrum Inbox\n address public inbox;\n /// Address of the (mock) Arbitrum Outbox\n address public outbox;\n /// Index of the next message on the inbox messages array\n uint256 public messageIndex;\n /// Inbox messages array\n bytes32[] public override inboxAccs;\n\n /**\n * @notice Deliver a message to the inbox. The encoded message will be\n * added to the inbox array, and messageIndex will be incremented.\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the message data\n * @return The next index for the inbox array\n */\n function deliverMessageToInbox(\n uint8 _kind,\n address _sender,\n bytes32 _messageDataHash\n ) external payable override returns (uint256) {\n messageIndex = messageIndex + 1;\n inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash)));\n emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash);\n return messageIndex;\n }\n\n /**\n * @notice Executes an L1 function call incoing from L2. This can only be called\n * by the Outbox.\n * @param _destAddr Contract to call\n * @param _amount ETH value to send\n * @param _data Calldata for the function call\n * @return True if the call was successful, false otherwise\n * @return Return data from the call\n */\n function executeCall(\n address _destAddr,\n uint256 _amount,\n bytes calldata _data\n ) external override returns (bool, bytes memory) {\n require(outbox == msg.sender, \"NOT_FROM_OUTBOX\");\n bool success;\n bytes memory returnData;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, returnData) = _destAddr.call{ value: _amount }(_data);\n emit BridgeCallTriggered(msg.sender, _destAddr, _amount, _data);\n return (success, returnData);\n }\n\n /**\n * @notice Set the address of the inbox. Anyone can call this, because it's a mock.\n * @param _inbox Address of the inbox\n * @param _enabled Enable the inbox (ignored)\n */\n function setInbox(address _inbox, bool _enabled) external override {\n inbox = _inbox;\n emit InboxToggle(inbox, _enabled);\n }\n\n /**\n * @notice Set the address of the outbox. Anyone can call this, because it's a mock.\n * @param _outbox Address of the outbox\n * @param _enabled Enable the outbox (ignored)\n */\n function setOutbox(address _outbox, bool _enabled) external override {\n outbox = _outbox;\n emit OutboxToggle(outbox, _enabled);\n }\n\n // View functions\n\n /**\n * @notice Getter for the active outbox (in this case there's only one)\n */\n function activeOutbox() external view override returns (address) {\n return outbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed inbox (in this case there's only one)\n * @param _inbox Address to check\n * @return True if the address is the allowed inbox, false otherwise\n */\n function allowedInboxes(address _inbox) external view override returns (bool) {\n return _inbox == inbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed outbox (in this case there's only one)\n * @param _outbox Address to check\n * @return True if the address is the allowed outbox, false otherwise\n */\n function allowedOutboxes(address _outbox) external view override returns (bool) {\n return _outbox == outbox;\n }\n\n /**\n * @notice Getter for the count of messages in the inboxAccs\n * @return Number of messages in inboxAccs\n */\n function messageCount() external view override returns (uint256) {\n return inboxAccs.length;\n }\n}\n" + }, + "contracts/tests/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock contract.\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @notice Contract Constructor.\n * @param _initialSupply Initial supply\n * @param _mintTo Address to whitch to mint the initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n\n /**\n * @notice Mint tokens to an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _to Address to mint tokens to\n * @param _amount Amount of tokens to mint\n */\n function bridgeMint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n\n /**\n * @notice Burn tokens from an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _from Address to burn tokens from\n * @param _amount Amount of tokens to burn\n */\n function bridgeBurn(address _from, uint256 _amount) external {\n _burn(_from, _amount);\n }\n}\n" + }, + "contracts/tests/InboxMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IInbox.sol\";\nimport \"./arbitrum/AddressAliasHelper.sol\";\n\n/**\n * @title Arbitrum Inbox mock contract\n * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes\n */\ncontract InboxMock is IInbox {\n /// @dev Type indicator for a standard L2 message\n uint8 internal constant L2_MSG = 3;\n /// @dev Type indicator for a retryable ticket message\n // solhint-disable-next-line const-name-snakecase\n uint8 internal constant L1MessageType_submitRetryableTx = 9;\n /// Address of the Bridge (mock) contract\n IBridge public override bridge;\n\n /**\n * @notice Send a message to L2 (by delivering it to the Bridge)\n * @param _messageData Encoded data to send in the message\n * @return Message number returned by the inbox\n */\n function sendL2Message(bytes calldata _messageData) external override returns (uint256) {\n uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @notice Set the address of the (mock) bridge\n * @param _bridge Address of the bridge\n */\n function setBridge(address _bridge) external {\n bridge = IBridge(_bridge);\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendContractTransaction(\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedContractTransaction(\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Creates a retryable ticket for an L2 transaction\n * @param _destAddr Address of the contract to call in L2\n * @param _arbTxCallValue Callvalue to use in the L2 transaction\n * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei\n * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost\n * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled\n * @param _maxGas Max gas for the L2 transcation\n * @param _gasPriceBid Gas price bid on L2\n * @param _data Encoded calldata for the L2 transaction (including function selector)\n * @return Message number returned by the bridge\n */\n function createRetryableTicket(\n address _destAddr,\n uint256 _arbTxCallValue,\n uint256 _maxSubmissionCost,\n address _submissionRefundAddress,\n address _valueRefundAddress,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable override returns (uint256) {\n _submissionRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_submissionRefundAddress);\n _valueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_valueRefundAddress);\n return\n _deliverMessage(\n L1MessageType_submitRetryableTx,\n msg.sender,\n abi.encodePacked(\n uint256(uint160(bytes20(_destAddr))),\n _arbTxCallValue,\n msg.value,\n _maxSubmissionCost,\n uint256(uint160(bytes20(_submissionRefundAddress))),\n uint256(uint160(bytes20(_valueRefundAddress))),\n _maxGas,\n _gasPriceBid,\n _data.length,\n _data\n )\n );\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function depositEth(uint256) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function pauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function unpauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function startRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function stopRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageData Encoded message data\n * @return Message number returned by the bridge\n */\n function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) {\n uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the encoded message data\n * @return Message number returned by the bridge\n */\n function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) {\n return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash);\n }\n}\n" + }, + "contracts/tests/L1TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\n\n/**\n * @title L1 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L1TokenGatewayMock is Ownable {\n using SafeMath for uint256;\n /// Next sequence number to return when outboundTransfer is called\n uint256 public nextSeqNum;\n\n /// @dev Emitted when a (fake) retryable ticket is created\n event FakeTxToL2(\n address from,\n uint256 value,\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 maxSubmissionCost,\n bytes outboundCalldata\n );\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2\n event DepositInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L1 Token Gateway Contract Constructor.\n */\n constructor() {}\n\n /**\n * @notice Creates and sends a fake retryable ticket to transfer GRT to L2.\n * This mock will actually just emit an event with parameters equivalent to what the real L1GraphTokenGateway\n * would send to L2.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _maxGas Gas limit for L2 execution of the ticket\n * @param _gasPriceBid Price per gas on L2\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return Sequence number of the retryable ticket created by Inbox (always )\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 seqNum = nextSeqNum;\n nextSeqNum += 1;\n {\n uint256 maxSubmissionCost;\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, maxSubmissionCost, extraData) = _parseOutboundData(_data);\n require(maxSubmissionCost > 0, \"NO_SUBMISSION_COST\");\n\n {\n // makes sure only sufficient ETH is supplied as required for successful redemption on L2\n // if a user does not desire immediate redemption they should provide\n // a msg.value of AT LEAST maxSubmissionCost\n uint256 expectedEth = maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(msg.value >= expectedEth, \"WRONG_ETH_VALUE\");\n }\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // transfer tokens to escrow\n IERC20(_l1Token).transferFrom(from, address(this), _amount);\n\n emit FakeTxToL2(from, msg.value, _maxGas, _gasPriceBid, maxSubmissionCost, outboundCalldata);\n }\n }\n emit DepositInitiated(_l1Token, from, _to, seqNum, _amount);\n\n return abi.encode(seqNum);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L2\n * Actually does nothing, just keeping it here as its useful to define the expected\n * calldata for the outgoing transfer in tests.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recepient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {}\n\n /**\n * @notice Creates calldata required to create a retryable ticket\n * @dev encodes the target function with its params which\n * will be called on L2 when the retryable ticket is redeemed\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L1 from which we're transferring tokens\n * @param _to Address on L2 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L2 transaction, which must be empty unless the caller is whitelisted\n * @return Encoded calldata (including function selector) for the L2 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n bytes memory emptyBytes;\n\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(emptyBytes, _data)\n );\n }\n\n /**\n * @notice Decodes calldata required for transfer of tokens to L2\n * @dev Data must include maxSubmissionCost, extraData can be left empty. When the router\n * sends an outbound message, data also contains the from address, but this mock\n * doesn't consider this case\n * @param _data Encoded callhook data containing maxSubmissionCost and extraData\n * @return Sender of the tx\n * @return Max ether value used to submit the retryable ticket\n * @return Additional data sent to L2\n */\n function _parseOutboundData(bytes memory _data) private view returns (address, uint256, bytes memory) {\n address from;\n uint256 maxSubmissionCost;\n bytes memory extraData;\n from = msg.sender;\n // User-encoded data contains the max retryable ticket submission cost\n // and additional L2 calldata\n (maxSubmissionCost, extraData) = abi.decode(_data, (uint256, bytes));\n return (from, maxSubmissionCost, extraData);\n }\n}\n" + }, + "contracts/tests/L2TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\nimport { GraphTokenMock } from \"./GraphTokenMock.sol\";\nimport { ICallhookReceiver } from \"../ICallhookReceiver.sol\";\n\n/**\n * @title L2 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L2TokenGatewayMock is Ownable {\n /// Address of the L1 GRT contract\n address public immutable l1Token;\n /// Address of the L2 GRT contract\n address public immutable l2Token;\n /// Next ID to return when sending an outboundTransfer\n uint256 public nextId;\n\n /// @dev Emitted when a (fake) transaction to L1 is created\n event FakeTxToL1(address from, bytes outboundCalldata);\n /// @dev Emitted when a (fake) retryable ticket is received from L1\n event DepositFinalized(address token, address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are withdrawn to L1 from L2\n event WithdrawalInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L2 Token Gateway Contract Constructor.\n * @param _l1Token Address of the L1 GRT contract\n * @param _l2Token Address of the L2 GRT contract\n */\n constructor(address _l1Token, address _l2Token) {\n l1Token = _l1Token;\n l2Token = _l2Token;\n }\n\n /**\n * @notice Creates and sends a (fake) transfer of GRT to L1.\n * This mock will actually just emit an event with parameters equivalent to what the real L2GraphTokenGateway\n * would send to L1.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return ID of the L2-L1 message (incrementing on every call)\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_l1Token == l1Token, \"INVALID_L1_TOKEN\");\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 id = nextId;\n nextId += 1;\n {\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, extraData) = _parseOutboundData(_data);\n\n require(msg.value == 0, \"!value\");\n require(extraData.length == 0, \"!extraData\");\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // burn tokens from the sender, they will be released from escrow in L1\n GraphTokenMock(l2Token).bridgeBurn(from, _amount);\n\n emit FakeTxToL1(from, outboundCalldata);\n }\n }\n emit WithdrawalInitiated(_l1Token, from, _to, id, _amount);\n\n return abi.encode(id);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L1\n * Implements calling callhooks if data is non-empty.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recipient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata, will trigger an onTokenTransfer call if non-empty\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {\n require(_l1Token == l1Token, \"TOKEN_NOT_GRT\");\n require(msg.value == 0, \"INVALID_NONZERO_VALUE\");\n\n GraphTokenMock(l2Token).bridgeMint(_to, _amount);\n\n if (_data.length > 0) {\n ICallhookReceiver(_to).onTokenTransfer(_from, _amount, _data);\n }\n\n emit DepositFinalized(_l1Token, _from, _to, _amount);\n }\n\n /**\n * @notice Calculate the L2 address of a bridged token\n * @dev In our case, this would only work for GRT.\n * @param l1ERC20 address of L1 GRT contract\n * @return L2 address of the bridged GRT token\n */\n function calculateL2TokenAddress(address l1ERC20) public view returns (address) {\n if (l1ERC20 != l1Token) {\n return address(0);\n }\n return l2Token;\n }\n\n /**\n * @notice Creates calldata required to create a tx to L1\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L2 from which we're transferring tokens\n * @param _to Address on L1 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L1 transaction, which must be empty\n * @return Encoded calldata (including function selector) for the L1 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(0, _data)\n );\n }\n\n /**\n * @dev Decodes calldata required for transfer of tokens to L1.\n * extraData can be left empty\n * @param _data Encoded callhook data\n * @return Sender of the tx\n * @return Any other data sent to L1\n */\n function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {\n address from;\n bytes memory extraData;\n // The mock doesn't take messages from the Router\n from = msg.sender;\n extraData = _data;\n return (from, extraData);\n }\n}\n" + }, + "contracts/tests/Stakes.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(\n Stakes.Indexer memory stake,\n uint256 _delegatedCapacity\n ) internal pure returns (uint256) {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "contracts/tests/StakingMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n receive() external payable {}\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/tests/WalletMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title WalletMock: a mock wallet contract for testing purposes\n * @dev For testing only, DO NOT USE IN PRODUCTION.\n * This is used to test L1-L2 transfer tools and to create scenarios\n * where an invalid wallet calls the transfer tool, e.g. a wallet that has an invalid\n * manager, or a wallet that has not been initialized.\n */\ncontract WalletMock {\n /// Target contract for the fallback function (usually a transfer tool contract)\n address public immutable target;\n /// Address of the GRT (mock) token\n address public immutable token;\n /// Address of the wallet's manager\n address public immutable manager;\n /// Whether the wallet has been initialized\n bool public immutable isInitialized;\n /// Whether the beneficiary has accepted the lock\n bool public immutable isAccepted;\n\n /**\n * @notice WalletMock constructor\n * @dev This constructor sets all the state variables so that\n * specific test scenarios can be created just by deploying this contract.\n * @param _target Target contract for the fallback function\n * @param _token Address of the GRT (mock) token\n * @param _manager Address of the wallet's manager\n * @param _isInitialized Whether the wallet has been initialized\n * @param _isAccepted Whether the beneficiary has accepted the lock\n */\n constructor(address _target, address _token, address _manager, bool _isInitialized, bool _isAccepted) {\n target = _target;\n token = _token;\n manager = _manager;\n isInitialized = _isInitialized;\n isAccepted = _isAccepted;\n }\n\n /**\n * @notice Fallback function\n * @dev This function calls the target contract with the data sent to this contract.\n * This is used to test the L1-L2 transfer tool.\n */\n fallback() external payable {\n // Call function with data\n Address.functionCall(target, msg.data);\n }\n\n /**\n * @notice Receive function\n * @dev This function is added to avoid compiler warnings, but just reverts.\n */\n receive() external payable {\n revert(\"Invalid call\");\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/mainnet/solcInputs/f0757d7c1c560a6ae9697525709a3f5b.json b/packages/token-distribution/deployments/mainnet/solcInputs/f0757d7c1c560a6ae9697525709a3f5b.json new file mode 100644 index 000000000..004c76be7 --- /dev/null +++ b/packages/token-distribution/deployments/mainnet/solcInputs/f0757d7c1c560a6ae9697525709a3f5b.json @@ -0,0 +1,65 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) private {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], MAX_UINT256);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n Ownable.initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n * \n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n Ownable.initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/rinkeby/.chainId b/packages/token-distribution/deployments/rinkeby/.chainId new file mode 100644 index 000000000..bf0d87ab1 --- /dev/null +++ b/packages/token-distribution/deployments/rinkeby/.chainId @@ -0,0 +1 @@ +4 \ No newline at end of file diff --git a/packages/token-distribution/deployments/rinkeby/GraphTokenLockManager.json b/packages/token-distribution/deployments/rinkeby/GraphTokenLockManager.json new file mode 100644 index 000000000..b9d151640 --- /dev/null +++ b/packages/token-distribution/deployments/rinkeby/GraphTokenLockManager.json @@ -0,0 +1,926 @@ +{ + "address": "0x9fb2369f2034FD857340D8388395861f07083616", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x45a0e8ebdc925f6eaeadd3e043bae0a8bd1b8c373641c90b6a341f1a40658906", + "receipt": { + "to": null, + "from": "0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9", + "contractAddress": "0x9fb2369f2034FD857340D8388395861f07083616", + "transactionIndex": 0, + "gasUsed": "3216552", + "logsBloom": "0x00000000000000000000000000000000000004000000000000800000000000000004000020000000000000000000000000000000000000008000000000000000000000000000000000000000000000000001000000000000000000400000000000000000020000000000000000000800000000000000000000000000000000400000000000020000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000080000000000000000000000000000000000000022000020000000000000000000000000000004000000000000000000000000000000000000", + "blockHash": "0xcff4d52fd60f740f879baa14b2acd6dda82825726cb3933cbfe713f6bd1e4ada", + "transactionHash": "0x45a0e8ebdc925f6eaeadd3e043bae0a8bd1b8c373641c90b6a341f1a40658906", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 7727644, + "transactionHash": "0x45a0e8ebdc925f6eaeadd3e043bae0a8bd1b8c373641c90b6a341f1a40658906", + "address": "0x9fb2369f2034FD857340D8388395861f07083616", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000023d1b1823e6cb5229137424f88c70fda1539f1f9" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xcff4d52fd60f740f879baa14b2acd6dda82825726cb3933cbfe713f6bd1e4ada" + }, + { + "transactionIndex": 0, + "blockNumber": 7727644, + "transactionHash": "0x45a0e8ebdc925f6eaeadd3e043bae0a8bd1b8c373641c90b6a341f1a40658906", + "address": "0x9fb2369f2034FD857340D8388395861f07083616", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x0000000000000000000000006eb5538d1e805a503893cd23ae980320eb8358c8" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0xcff4d52fd60f740f879baa14b2acd6dda82825726cb3933cbfe713f6bd1e4ada" + } + ], + "blockNumber": 7727644, + "cumulativeGasUsed": "3216552", + "status": 1, + "byzantium": true + }, + "args": [ + "0xB0a7bC0e6b51db8Cfda3f80904c8E35259F1abDb", + "0x6Eb5538d1E805a503893Cd23AE980320Eb8358C8" + ], + "solcInputHash": "a72ab6278ade6c5c10115f7be2c555c9", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address)\":{\"params\":{\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/GSN/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../GSN/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xf7c39c7e6d06ed3bda90cfefbcbf2ddc32c599c3d6721746546ad64946efccaa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x3b21f2c8d626de3b9925ae33e972d8bf5c8b1bffb3f4ee94daeed7d0679036e6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa6a15ddddcbf29d2922a1e0d4151b5d2d33da24b93cc9ebc12390e0d855532f8\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint256(_data));\\n }\\n}\\n\",\"keccak256\":\"0x3545c88fb28fb3934362d06c8dd5ccdfa951378c3be319a20c53f285520cace3\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(value)));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(value)));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(value)));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint256(_at(set._inner, index)));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0xae0992eb1ec30fd1ecdf2e04a6036decfc9797bf11dc1ec84b546b74318d5ec2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 private _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSignature(\\n \\\"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\\\",\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\\n external\\n override\\n onlyOwner\\n {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solium-disable-next-line security/no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x0384d62cb600eb4128baacf5bca60ea2cb0b68d2d013479daef65ed5f15446ef\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability { NotSet, Enabled, Disabled }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0x396f8102fb03d884d599831989d9753a69f0d9b65538c8206c81e0067827c5a2\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n// Based on https://eips.ethereum.org/EIPS/eip-1167\\ncontract MinimalProxyFactory is Ownable {\\n // -- Events --\\n\\n event ProxyCreated(address indexed proxy);\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\\n }\\n\\n /**\\n * @notice Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(\\n bytes32 _salt,\\n address _implementation,\\n bytes memory _data\\n ) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @notice Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0x8aa3d50e714f92dc0ed6cc6d88fa8a18c948493103928f6092f98815b2c046ca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003d7538038062003d75833981810160405281019062000037919062000384565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004cf565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b50506200057e565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146200025c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200025390620004ad565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002cf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002c6906200048b565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008151905062000367816200054a565b92915050565b6000815190506200037e8162000564565b92915050565b600080604083850312156200039857600080fd5b6000620003a8858286016200036d565b9250506020620003bb8582860162000356565b9150509250929050565b6000620003d4601983620004f1565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b600062000416602083620004f1565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b600062000458601483620004f1565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004a681620003c5565b9050919050565b60006020820190508181036000830152620004c88162000407565b9050919050565b60006020820190508181036000830152620004ea8162000449565b9050919050565b600082825260208201905092915050565b60006200050f826200052a565b9050919050565b6000620005238262000502565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b620005558162000502565b81146200056157600080fd5b50565b6200056f8162000516565b81146200057b57600080fd5b50565b6137e7806200058e6000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b60048036038101906101469190612638565b6103bb565b005b6101676004803603810190610162919061260f565b61057c565b6040516101749190613127565b60405180910390f35b610197600480360381019061019291906126d5565b6105bd565b005b6101b360048036038101906101ae919061267d565b610733565b005b6101cf60048036038101906101ca9190612446565b6107d8565b005b6101eb60048036038101906101e6919061246f565b610982565b005b6102076004803603810190610202919061260f565b610cfb565b6040516102149190612f61565b60405180910390f35b610225610d2e565b005b610241600480360381019061023c9190612446565b610e81565b60405161024e9190613127565b60405180910390f35b61025f610e9e565b60405161026c9190612f61565b60405180910390f35b61028f600480360381019061028a9190612535565b610ec7565b005b61029961100d565b6040516102a69190613105565b60405180910390f35b6102b76110e5565b6040516102c49190612f61565b60405180910390f35b6102e760048036038101906102e291906126d5565b61110b565b005b61030360048036038101906102fe91906125d3565b6111ee565b6040516103109190612f61565b60405180910390f35b610333600480360381019061032e9190612446565b611212565b005b61034f600480360381019061034a9190612446565b61134c565b005b61036b6004803603810190610366919061260f565b6114d8565b6040516103789190612f61565b60405180910390f35b61039b60048036038101906103969190612446565b611553565b005b6103a5611715565b6040516103b29190613142565b60405180910390f35b6103c361173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610450576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044790613323565b60405180910390fd5b600061045c8383611747565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9868660405161056f92919061315d565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff1661059e836114d8565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105c561173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064990613323565b60405180910390fd5b60008111610695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90613303565b60405180910390fd5b6106e23382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117d59092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516107289190613403565b60405180910390a250565b61073b61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613323565b60405180910390fd5b6107d383838361185b565b505050565b6107e061173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461086d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161086490613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156108dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d490613203565b60405180910390fd5b6108f1816002611a3d90919063ffffffff16565b610930576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161092790613363565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960016040516109779190613127565b60405180910390a250565b61098a61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0e90613323565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a739190612f61565b60206040518083038186803b158015610a8b57600080fd5b505afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac391906126fe565b1015610b04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afb90613243565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610b4d9b9a99989796959493929190612f7c565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610c028280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a6d565b9050610c51818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117d59092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610ce6989796959493929190613087565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d3661173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610dc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dba90613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e97826002611ae990919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610ecf61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5390613323565b60405180910390fd5b818190508484905014610fa4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b906131e3565b60405180910390fd5b60005b8484905081101561100657610ff9858583818110610fc157fe5b9050602002810190610fd3919061341e565b858585818110610fdf57fe5b9050602002016020810190610ff49190612446565b61185b565b8080600101915050610fa7565b5050505050565b60608061101a6002611b19565b67ffffffffffffffff8111801561103057600080fd5b5060405190808252806020026020018201604052801561105f5781602001602082028036833780820191505090505b50905060005b61106f6002611b19565b8110156110dd5761108a816002611b2e90919063ffffffff16565b82828151811061109657fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611065565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161114e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114590613303565b60405180910390fd5b61119d333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611b48909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111e39190613403565b60405180910390a250565b600061120a836111fd84611bd1565b8051906020012030611c47565b905092915050565b61121a61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129e90613323565b60405180910390fd5b6112bb816002611c8b90919063ffffffff16565b6112fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f190613283565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516113419190613127565b60405180910390a250565b61135461173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146113e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113d890613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611451576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611448906132a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61155b61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146115e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115df90613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164f90613223565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006117cd83836040516024016040516020818303038152906040529190604051611773929190612f48565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611cbb565b905092915050565b6118568363a9059cbb60e01b84846040516024016117f492919061305e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d13565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c1906132c3565b60405180910390fd5b6118d381611dda565b611912576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611909906133e3565b60405180910390fd5b600061191e8484611747565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611a2f92919061315d565b60405180910390a450505050565b6000611a65836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ded565b905092915050565b600080611a84600086611a7f87611bd1565b611e5d565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611ade57611adc8184611f6e565b505b809150509392505050565b6000611b11836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611fb8565b905092915050565b6000611b2782600001611fdb565b9050919050565b6000611b3d8360000183611fec565b60001c905092915050565b611bcb846323b872dd60e01b858585604051602401611b6993929190613027565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d13565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611c2d9493929190612e95565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611c659493929190612ee3565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611cb3836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612059565b905092915050565b60006004825114611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890613343565b60405180910390fd5b60006020830151905080915050919050565b6060611d75826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121419092919063ffffffff16565b9050600081511115611dd55780806020019051810190611d9591906125aa565b611dd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dcb906133a3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611df98383611fb8565b611e52578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611e57565b600090505b92915050565b60008084471015611ea3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9a906133c3565b60405180910390fd5b600083511415611ee8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611edf906131c3565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f63576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5a906132e3565b60405180910390fd5b809150509392505050565b6060611fb083836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612141565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202e906131a3565b60405180910390fd5b82600001828154811061204657fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461213557600060018203905060006001866000018054905003905060008660000182815481106120a457fe5b90600052602060002001549050808760000184815481106120c157fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806120f957fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061213b565b60009150505b92915050565b60606121508484600085612159565b90509392505050565b60608247101561219e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219590613263565b60405180910390fd5b6121a785611dda565b6121e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121dd90613383565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516122109190612f31565b60006040518083038185875af1925050503d806000811461224d576040519150601f19603f3d011682016040523d82523d6000602084013e612252565b606091505b509150915061226282828661226e565b92505050949350505050565b6060831561227e578290506122ce565b6000835111156122915782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122c59190613181565b60405180910390fd5b9392505050565b6000813590506122e48161372e565b92915050565b60008083601f8401126122fc57600080fd5b8235905067ffffffffffffffff81111561231557600080fd5b60208301915083602082028301111561232d57600080fd5b9250929050565b60008083601f84011261234657600080fd5b8235905067ffffffffffffffff81111561235f57600080fd5b60208301915083602082028301111561237757600080fd5b9250929050565b60008151905061238d81613745565b92915050565b6000813590506123a28161375c565b92915050565b6000813590506123b781613773565b92915050565b6000813590506123cc8161378a565b92915050565b60008083601f8401126123e457600080fd5b8235905067ffffffffffffffff8111156123fd57600080fd5b60208301915083600182028301111561241557600080fd5b9250929050565b60008135905061242b8161379a565b92915050565b6000815190506124408161379a565b92915050565b60006020828403121561245857600080fd5b6000612466848285016122d5565b91505092915050565b60008060008060008060008060006101208a8c03121561248e57600080fd5b600061249c8c828d016122d5565b99505060206124ad8c828d016122d5565b98505060406124be8c828d0161241c565b97505060606124cf8c828d0161241c565b96505060806124e08c828d0161241c565b95505060a06124f18c828d0161241c565b94505060c06125028c828d0161241c565b93505060e06125138c828d0161241c565b9250506101006125258c828d016123bd565b9150509295985092959850929598565b6000806000806040858703121561254b57600080fd5b600085013567ffffffffffffffff81111561256557600080fd5b61257187828801612334565b9450945050602085013567ffffffffffffffff81111561259057600080fd5b61259c878288016122ea565b925092505092959194509250565b6000602082840312156125bc57600080fd5b60006125ca8482850161237e565b91505092915050565b600080604083850312156125e657600080fd5b60006125f485828601612393565b9250506020612605858286016122d5565b9150509250929050565b60006020828403121561262157600080fd5b600061262f848285016123a8565b91505092915050565b6000806020838503121561264b57600080fd5b600083013567ffffffffffffffff81111561266557600080fd5b612671858286016123d2565b92509250509250929050565b60008060006040848603121561269257600080fd5b600084013567ffffffffffffffff8111156126ac57600080fd5b6126b8868287016123d2565b935093505060206126cb868287016122d5565b9150509250925092565b6000602082840312156126e757600080fd5b60006126f58482850161241c565b91505092915050565b60006020828403121561271057600080fd5b600061271e84828501612431565b91505092915050565b6000612733838361273f565b60208301905092915050565b612748816134eb565b82525050565b612757816134eb565b82525050565b61276e612769826134eb565b6136a4565b82525050565b600061277f82613485565b61278981856134b3565b935061279483613475565b8060005b838110156127c55781516127ac8882612727565b97506127b7836134a6565b925050600181019050612798565b5085935050505092915050565b6127db816134fd565b82525050565b6127f26127ed82613535565b6136c0565b82525050565b61280961280482613561565b6136ca565b82525050565b61282061281b82613509565b6136b6565b82525050565b6128376128328261358d565b6136d4565b82525050565b61284e612849826135b9565b6136de565b82525050565b600061285f82613490565b61286981856134c4565b9350612879818560208601613671565b80840191505092915050565b61288e8161362c565b82525050565b61289d81613650565b82525050565b60006128af83856134cf565b93506128bc838584613662565b6128c5836136fc565b840190509392505050565b60006128dc83856134e0565b93506128e9838584613662565b82840190509392505050565b60006129008261349b565b61290a81856134cf565b935061291a818560208601613671565b612923816136fc565b840191505092915050565b600061293b6022836134cf565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129a16020836134cf565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006129e16015836134cf565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612a21601a836134cf565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000612a616026836134cf565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612ac76020836134cf565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612b076026836134cf565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612b6d601b836134cf565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612bad6019836134cf565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612bed601d836134cf565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612c2d6019836134cf565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612c6d6015836134cf565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612cad6020836134cf565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612ced6018836134cf565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612d2d6019836134cf565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612d6d601d836134cf565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612dad602a836134cf565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612e13601d836134cf565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612e536019836134cf565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612e8f81613622565b82525050565b6000612ea182876127e1565b600a82019150612eb182866127e1565b600a82019150612ec18285612826565b601482019150612ed182846127f8565b600f8201915081905095945050505050565b6000612eef828761280f565b600182019150612eff828661275d565b601482019150612f0f828561283d565b602082019150612f1f828461283d565b60208201915081905095945050505050565b6000612f3d8284612854565b915081905092915050565b6000612f558284866128d0565b91508190509392505050565b6000602082019050612f76600083018461274e565b92915050565b600061016082019050612f92600083018e61274e565b612f9f602083018d61274e565b612fac604083018c61274e565b612fb9606083018b61274e565b612fc6608083018a612e86565b612fd360a0830189612e86565b612fe060c0830188612e86565b612fed60e0830187612e86565b612ffb610100830186612e86565b613009610120830185612e86565b613017610140830184612894565b9c9b505050505050505050505050565b600060608201905061303c600083018661274e565b613049602083018561274e565b6130566040830184612e86565b949350505050565b6000604082019050613073600083018561274e565b6130806020830184612e86565b9392505050565b60006101008201905061309d600083018b61274e565b6130aa602083018a612e86565b6130b76040830189612e86565b6130c46060830188612e86565b6130d16080830187612e86565b6130de60a0830186612e86565b6130eb60c0830185612e86565b6130f860e0830184612894565b9998505050505050505050565b6000602082019050818103600083015261311f8184612774565b905092915050565b600060208201905061313c60008301846127d2565b92915050565b60006020820190506131576000830184612885565b92915050565b600060208201905081810360008301526131788184866128a3565b90509392505050565b6000602082019050818103600083015261319b81846128f5565b905092915050565b600060208201905081810360008301526131bc8161292e565b9050919050565b600060208201905081810360008301526131dc81612994565b9050919050565b600060208201905081810360008301526131fc816129d4565b9050919050565b6000602082019050818103600083015261321c81612a14565b9050919050565b6000602082019050818103600083015261323c81612a54565b9050919050565b6000602082019050818103600083015261325c81612aba565b9050919050565b6000602082019050818103600083015261327c81612afa565b9050919050565b6000602082019050818103600083015261329c81612b60565b9050919050565b600060208201905081810360008301526132bc81612ba0565b9050919050565b600060208201905081810360008301526132dc81612be0565b9050919050565b600060208201905081810360008301526132fc81612c20565b9050919050565b6000602082019050818103600083015261331c81612c60565b9050919050565b6000602082019050818103600083015261333c81612ca0565b9050919050565b6000602082019050818103600083015261335c81612ce0565b9050919050565b6000602082019050818103600083015261337c81612d20565b9050919050565b6000602082019050818103600083015261339c81612d60565b9050919050565b600060208201905081810360008301526133bc81612da0565b9050919050565b600060208201905081810360008301526133dc81612e06565b9050919050565b600060208201905081810360008301526133fc81612e46565b9050919050565b60006020820190506134186000830184612e86565b92915050565b6000808335600160200384360303811261343757600080fd5b80840192508235915067ffffffffffffffff82111561345557600080fd5b60208301925060018202360383131561346d57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006134f682613602565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506135fd8261371a565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006136378261363e565b9050919050565b600061364982613602565b9050919050565b600061365b826135ef565b9050919050565b82818337600083830152505050565b60005b8381101561368f578082015181840152602081019050613674565b8381111561369e576000848401525b50505050565b60006136af826136e8565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006136f38261370d565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061372b5761372a6136fa565b5b50565b613737816134eb565b811461374257600080fd5b50565b61374e816134fd565b811461375957600080fd5b50565b613765816135b9565b811461377057600080fd5b50565b61377c816135c3565b811461378757600080fd5b50565b6003811061379757600080fd5b50565b6137a381613622565b81146137ae57600080fd5b5056fea2646970667358221220ce8e84f89eb556f2f74739a29d42b007afeaac5ac92a1454d6c07fa4523a0a9564736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c80639c05fc60116100ad578063c1ab13db11610071578063c1ab13db14610319578063cf497e6c14610335578063f1d24c4514610351578063f2fde38b14610381578063fc0c546a1461039d5761012c565b80639c05fc6014610275578063a345746614610291578063a619486e146102af578063b6b55f25146102cd578063bdb62fbe146102e95761012c565b806368d30c2e116100f457806368d30c2e146101d15780636e03b8dc146101ed578063715018a61461021d57806379ee1bdf146102275780638da5cb5b146102575761012c565b806303990a6c146101315780630602ba2b1461014d5780632e1a7d4d1461017d578063463013a2146101995780635975e00c146101b5575b600080fd5b61014b60048036038101906101469190612638565b6103bb565b005b6101676004803603810190610162919061260f565b61057c565b6040516101749190613127565b60405180910390f35b610197600480360381019061019291906126d5565b6105bd565b005b6101b360048036038101906101ae919061267d565b610733565b005b6101cf60048036038101906101ca9190612446565b6107d8565b005b6101eb60048036038101906101e6919061246f565b610982565b005b6102076004803603810190610202919061260f565b610cfb565b6040516102149190612f61565b60405180910390f35b610225610d2e565b005b610241600480360381019061023c9190612446565b610e81565b60405161024e9190613127565b60405180910390f35b61025f610e9e565b60405161026c9190612f61565b60405180910390f35b61028f600480360381019061028a9190612535565b610ec7565b005b61029961100d565b6040516102a69190613105565b60405180910390f35b6102b76110e5565b6040516102c49190612f61565b60405180910390f35b6102e760048036038101906102e291906126d5565b61110b565b005b61030360048036038101906102fe91906125d3565b6111ee565b6040516103109190612f61565b60405180910390f35b610333600480360381019061032e9190612446565b611212565b005b61034f600480360381019061034a9190612446565b61134c565b005b61036b6004803603810190610366919061260f565b6114d8565b6040516103789190612f61565b60405180910390f35b61039b60048036038101906103969190612446565b611553565b005b6103a5611715565b6040516103b29190613142565b60405180910390f35b6103c361173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610450576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161044790613323565b60405180910390fd5b600061045c8383611747565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c9868660405161056f92919061315d565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff1661059e836114d8565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105c561173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161064990613323565b60405180910390fd5b60008111610695576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161068c90613303565b60405180910390fd5b6106e23382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117d59092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516107289190613403565b60405180910390a250565b61073b61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146107c8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107bf90613323565b60405180910390fd5b6107d383838361185b565b505050565b6107e061173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461086d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161086490613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156108dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d490613203565b60405180910390fd5b6108f1816002611a3d90919063ffffffff16565b610930576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161092790613363565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960016040516109779190613127565b60405180910390a250565b61098a61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610a17576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a0e90613323565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a739190612f61565b60206040518083038186803b158015610a8b57600080fd5b505afa158015610a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ac391906126fe565b1015610b04576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610afb90613243565b60405180910390fd5b6060308a8a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168b8b8b8b8b8b8b604051602401610b4d9b9a99989796959493929190612f7c565b6040516020818303038152906040527fbd896dcb000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610c028280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a6d565b9050610c51818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117d59092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610ce6989796959493929190613087565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d3661173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610dc3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dba90613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e97826002611ae990919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610ecf61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f5390613323565b60405180910390fd5b818190508484905014610fa4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f9b906131e3565b60405180910390fd5b60005b8484905081101561100657610ff9858583818110610fc157fe5b9050602002810190610fd3919061341e565b858585818110610fdf57fe5b9050602002016020810190610ff49190612446565b61185b565b8080600101915050610fa7565b5050505050565b60608061101a6002611b19565b67ffffffffffffffff8111801561103057600080fd5b5060405190808252806020026020018201604052801561105f5781602001602082028036833780820191505090505b50905060005b61106f6002611b19565b8110156110dd5761108a816002611b2e90919063ffffffff16565b82828151811061109657fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050611065565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000811161114e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161114590613303565b60405180910390fd5b61119d333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611b48909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e826040516111e39190613403565b60405180910390a250565b600061120a836111fd84611bd1565b8051906020012030611c47565b905092915050565b61121a61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146112a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161129e90613323565b60405180910390fd5b6112bb816002611c8b90919063ffffffff16565b6112fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112f190613283565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516113419190613127565b60405180910390a250565b61135461173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146113e1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113d890613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611451576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611448906132a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b61155b61173f565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146115e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016115df90613323565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611658576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161164f90613223565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b60006117cd83836040516024016040516020818303038152906040529190604051611773929190612f48565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611cbb565b905092915050565b6118568363a9059cbb60e01b84846040516024016117f492919061305e565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d13565b505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118c1906132c3565b60405180910390fd5b6118d381611dda565b611912576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611909906133e3565b60405180910390fd5b600061191e8484611747565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611a2f92919061315d565b60405180910390a450505050565b6000611a65836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ded565b905092915050565b600080611a84600086611a7f87611bd1565b611e5d565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611ade57611adc8184611f6e565b505b809150509392505050565b6000611b11836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611fb8565b905092915050565b6000611b2782600001611fdb565b9050919050565b6000611b3d8360000183611fec565b60001c905092915050565b611bcb846323b872dd60e01b858585604051602401611b6993929190613027565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611d13565b50505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b905083838383604051602001611c2d9493929190612e95565b604051602081830303815290604052945050505050919050565b60008060ff60f81b838686604051602001611c659493929190612ee3565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b6000611cb3836000018373ffffffffffffffffffffffffffffffffffffffff1660001b612059565b905092915050565b60006004825114611d01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cf890613343565b60405180910390fd5b60006020830151905080915050919050565b6060611d75826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166121419092919063ffffffff16565b9050600081511115611dd55780806020019051810190611d9591906125aa565b611dd4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dcb906133a3565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611df98383611fb8565b611e52578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611e57565b600090505b92915050565b60008084471015611ea3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9a906133c3565b60405180910390fd5b600083511415611ee8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611edf906131c3565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611f63576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f5a906132e3565b60405180910390fd5b809150509392505050565b6060611fb083836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612141565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011612037576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161202e906131a3565b60405180910390fd5b82600001828154811061204657fe5b9060005260206000200154905092915050565b6000808360010160008481526020019081526020016000205490506000811461213557600060018203905060006001866000018054905003905060008660000182815481106120a457fe5b90600052602060002001549050808760000184815481106120c157fe5b90600052602060002001819055506001830187600101600083815260200190815260200160002081905550866000018054806120f957fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061213b565b60009150505b92915050565b60606121508484600085612159565b90509392505050565b60608247101561219e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161219590613263565b60405180910390fd5b6121a785611dda565b6121e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121dd90613383565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516122109190612f31565b60006040518083038185875af1925050503d806000811461224d576040519150601f19603f3d011682016040523d82523d6000602084013e612252565b606091505b509150915061226282828661226e565b92505050949350505050565b6060831561227e578290506122ce565b6000835111156122915782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122c59190613181565b60405180910390fd5b9392505050565b6000813590506122e48161372e565b92915050565b60008083601f8401126122fc57600080fd5b8235905067ffffffffffffffff81111561231557600080fd5b60208301915083602082028301111561232d57600080fd5b9250929050565b60008083601f84011261234657600080fd5b8235905067ffffffffffffffff81111561235f57600080fd5b60208301915083602082028301111561237757600080fd5b9250929050565b60008151905061238d81613745565b92915050565b6000813590506123a28161375c565b92915050565b6000813590506123b781613773565b92915050565b6000813590506123cc8161378a565b92915050565b60008083601f8401126123e457600080fd5b8235905067ffffffffffffffff8111156123fd57600080fd5b60208301915083600182028301111561241557600080fd5b9250929050565b60008135905061242b8161379a565b92915050565b6000815190506124408161379a565b92915050565b60006020828403121561245857600080fd5b6000612466848285016122d5565b91505092915050565b60008060008060008060008060006101208a8c03121561248e57600080fd5b600061249c8c828d016122d5565b99505060206124ad8c828d016122d5565b98505060406124be8c828d0161241c565b97505060606124cf8c828d0161241c565b96505060806124e08c828d0161241c565b95505060a06124f18c828d0161241c565b94505060c06125028c828d0161241c565b93505060e06125138c828d0161241c565b9250506101006125258c828d016123bd565b9150509295985092959850929598565b6000806000806040858703121561254b57600080fd5b600085013567ffffffffffffffff81111561256557600080fd5b61257187828801612334565b9450945050602085013567ffffffffffffffff81111561259057600080fd5b61259c878288016122ea565b925092505092959194509250565b6000602082840312156125bc57600080fd5b60006125ca8482850161237e565b91505092915050565b600080604083850312156125e657600080fd5b60006125f485828601612393565b9250506020612605858286016122d5565b9150509250929050565b60006020828403121561262157600080fd5b600061262f848285016123a8565b91505092915050565b6000806020838503121561264b57600080fd5b600083013567ffffffffffffffff81111561266557600080fd5b612671858286016123d2565b92509250509250929050565b60008060006040848603121561269257600080fd5b600084013567ffffffffffffffff8111156126ac57600080fd5b6126b8868287016123d2565b935093505060206126cb868287016122d5565b9150509250925092565b6000602082840312156126e757600080fd5b60006126f58482850161241c565b91505092915050565b60006020828403121561271057600080fd5b600061271e84828501612431565b91505092915050565b6000612733838361273f565b60208301905092915050565b612748816134eb565b82525050565b612757816134eb565b82525050565b61276e612769826134eb565b6136a4565b82525050565b600061277f82613485565b61278981856134b3565b935061279483613475565b8060005b838110156127c55781516127ac8882612727565b97506127b7836134a6565b925050600181019050612798565b5085935050505092915050565b6127db816134fd565b82525050565b6127f26127ed82613535565b6136c0565b82525050565b61280961280482613561565b6136ca565b82525050565b61282061281b82613509565b6136b6565b82525050565b6128376128328261358d565b6136d4565b82525050565b61284e612849826135b9565b6136de565b82525050565b600061285f82613490565b61286981856134c4565b9350612879818560208601613671565b80840191505092915050565b61288e8161362c565b82525050565b61289d81613650565b82525050565b60006128af83856134cf565b93506128bc838584613662565b6128c5836136fc565b840190509392505050565b60006128dc83856134e0565b93506128e9838584613662565b82840190509392505050565b60006129008261349b565b61290a81856134cf565b935061291a818560208601613671565b612923816136fc565b840191505092915050565b600061293b6022836134cf565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006129a16020836134cf565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b60006129e16015836134cf565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b6000612a21601a836134cf565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000612a616026836134cf565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612ac76020836134cf565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612b076026836134cf565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612b6d601b836134cf565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612bad6019836134cf565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612bed601d836134cf565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612c2d6019836134cf565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612c6d6015836134cf565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612cad6020836134cf565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612ced6018836134cf565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612d2d6019836134cf565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612d6d601d836134cf565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612dad602a836134cf565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612e13601d836134cf565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612e536019836134cf565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612e8f81613622565b82525050565b6000612ea182876127e1565b600a82019150612eb182866127e1565b600a82019150612ec18285612826565b601482019150612ed182846127f8565b600f8201915081905095945050505050565b6000612eef828761280f565b600182019150612eff828661275d565b601482019150612f0f828561283d565b602082019150612f1f828461283d565b60208201915081905095945050505050565b6000612f3d8284612854565b915081905092915050565b6000612f558284866128d0565b91508190509392505050565b6000602082019050612f76600083018461274e565b92915050565b600061016082019050612f92600083018e61274e565b612f9f602083018d61274e565b612fac604083018c61274e565b612fb9606083018b61274e565b612fc6608083018a612e86565b612fd360a0830189612e86565b612fe060c0830188612e86565b612fed60e0830187612e86565b612ffb610100830186612e86565b613009610120830185612e86565b613017610140830184612894565b9c9b505050505050505050505050565b600060608201905061303c600083018661274e565b613049602083018561274e565b6130566040830184612e86565b949350505050565b6000604082019050613073600083018561274e565b6130806020830184612e86565b9392505050565b60006101008201905061309d600083018b61274e565b6130aa602083018a612e86565b6130b76040830189612e86565b6130c46060830188612e86565b6130d16080830187612e86565b6130de60a0830186612e86565b6130eb60c0830185612e86565b6130f860e0830184612894565b9998505050505050505050565b6000602082019050818103600083015261311f8184612774565b905092915050565b600060208201905061313c60008301846127d2565b92915050565b60006020820190506131576000830184612885565b92915050565b600060208201905081810360008301526131788184866128a3565b90509392505050565b6000602082019050818103600083015261319b81846128f5565b905092915050565b600060208201905081810360008301526131bc8161292e565b9050919050565b600060208201905081810360008301526131dc81612994565b9050919050565b600060208201905081810360008301526131fc816129d4565b9050919050565b6000602082019050818103600083015261321c81612a14565b9050919050565b6000602082019050818103600083015261323c81612a54565b9050919050565b6000602082019050818103600083015261325c81612aba565b9050919050565b6000602082019050818103600083015261327c81612afa565b9050919050565b6000602082019050818103600083015261329c81612b60565b9050919050565b600060208201905081810360008301526132bc81612ba0565b9050919050565b600060208201905081810360008301526132dc81612be0565b9050919050565b600060208201905081810360008301526132fc81612c20565b9050919050565b6000602082019050818103600083015261331c81612c60565b9050919050565b6000602082019050818103600083015261333c81612ca0565b9050919050565b6000602082019050818103600083015261335c81612ce0565b9050919050565b6000602082019050818103600083015261337c81612d20565b9050919050565b6000602082019050818103600083015261339c81612d60565b9050919050565b600060208201905081810360008301526133bc81612da0565b9050919050565b600060208201905081810360008301526133dc81612e06565b9050919050565b600060208201905081810360008301526133fc81612e46565b9050919050565b60006020820190506134186000830184612e86565b92915050565b6000808335600160200384360303811261343757600080fd5b80840192508235915067ffffffffffffffff82111561345557600080fd5b60208301925060018202360383131561346d57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b60006134f682613602565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b60008190506135fd8261371a565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006136378261363e565b9050919050565b600061364982613602565b9050919050565b600061365b826135ef565b9050919050565b82818337600083830152505050565b60005b8381101561368f578082015181840152602081019050613674565b8381111561369e576000848401525b50505050565b60006136af826136e8565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006136f38261370d565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b6003811061372b5761372a6136fa565b5b50565b613737816134eb565b811461374257600080fd5b50565b61374e816134fd565b811461375957600080fd5b50565b613765816135b9565b811461377057600080fd5b50565b61377c816135c3565b811461378757600080fd5b50565b6003811061379757600080fd5b50565b6137a381613622565b81146137ae57600080fd5b5056fea2646970667358221220ce8e84f89eb556f2f74739a29d42b007afeaac5ac92a1454d6c07fa4523a0a9564736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address)": { + "params": { + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 30, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3003, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3005, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)1749_storage" + }, + { + "astId": 3007, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3009, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)908" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)908": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)1749_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 1748, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)1484_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)1484_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 1479, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 1483, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/rinkeby/GraphTokenLockWallet.json b/packages/token-distribution/deployments/rinkeby/GraphTokenLockWallet.json new file mode 100644 index 000000000..0f70b7d37 --- /dev/null +++ b/packages/token-distribution/deployments/rinkeby/GraphTokenLockWallet.json @@ -0,0 +1,968 @@ +{ + "address": "0x6Eb5538d1E805a503893Cd23AE980320Eb8358C8", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x071fb2ebafb0e8fb68ee80f73f0ed0ee557a238e216cfb247fb6ac64544c0c75", + "receipt": { + "to": null, + "from": "0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9", + "contractAddress": "0x6Eb5538d1E805a503893Cd23AE980320Eb8358C8", + "transactionIndex": 0, + "gasUsed": "3149102", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf3b421de1dd45e116c84fd76b143c22cece825ff96bac9291cb25a9104e982e8", + "transactionHash": "0x071fb2ebafb0e8fb68ee80f73f0ed0ee557a238e216cfb247fb6ac64544c0c75", + "logs": [], + "blockNumber": 7727643, + "cumulativeGasUsed": "3149102", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "a72ab6278ade6c5c10115f7be2c555c9", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule and takes into account already released tokens\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x3b21f2c8d626de3b9925ae33e972d8bf5c8b1bffb3f4ee94daeed7d0679036e6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa6a15ddddcbf29d2922a1e0d4151b5d2d33da24b93cc9ebc12390e0d855532f8\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n uint256 public releasedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n Ownable.initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public override view returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public override view returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public override view returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public override view returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public override view returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public override view returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public override view returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public override view returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public override view returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public override view returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public override view returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public override view returns (uint256) {\\n return managedAmount.sub(releasedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public override view returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0x4bb186cde23ff896ec75e825b3944e480bd56ec6055cf68b704ba9e44e3aa495\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n uint256 private constant MAX_UINT256 = 2**256 - 1;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) private {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], MAX_UINT256);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n token.safeApprove(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc9615104e2bb94e163e6db227089b950e33de804ad811b5d45242f2beca192b4\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability { NotSet, Enabled, Disabled }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0x396f8102fb03d884d599831989d9753a69f0d9b65538c8206c81e0067827c5a2\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xc93c7362ac4d74b624b48517985f92c277ce90ae6e5ccb706e70a61af5752077\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061384c806100206000396000f3fe60806040526004361061021e5760003560e01c806386d00e0211610123578063bc0163c1116100ab578063e8dda6f51161006f578063e8dda6f514610c51578063e97d87d514610c7c578063ebbab99214610ca7578063f2fde38b14610cd2578063fc0c546a14610d235761021f565b8063bc0163c114610a84578063bd896dcb14610aaf578063ce845d1d14610baa578063d0ebdbe714610bd5578063d18e81b314610c265761021f565b806391f7cfb9116100f257806391f7cfb9146109b1578063a4caeb42146109dc578063b0d1818c14610a07578063b470aade14610a42578063b6549f7514610a6d5761021f565b806386d00e02146108f857806386d1a69f14610923578063872a78101461093a5780638da5cb5b146109705761021f565b8063398057a3116101a65780635b940081116101755780635b9400811461084957806360e7994414610874578063715018a61461088b57806378e97925146108a25780637bdf05af146108cd5761021f565b8063398057a31461078757806344b1231f146107b257806345d30a17146107dd578063481c6a75146108085761021f565b80632a627814116101ed5780632a627814146106aa5780632bc9ed02146106c15780633197cbb6146106ee57806338af3eed14610719578063392e53cd1461075a5761021f565b8063029c6c9f146105fe57806306040618146106295780630dff24d5146106545780630fb5a6b41461067f5761021f565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561039a57600080fd5b505afa1580156103ae573d6000803e3d6000fd5b505050506040513d60208110156103c457600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561047a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b6000610484610d64565b90506104d5826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610e2f565b50600160028111156104e357fe5b600960009054906101000a900460ff1660028111156104fe57fe5b14156105fa57600061050e610d64565b90508181101561055057600061052d8284610e7990919063ffffffff16565b905061054481600c54610ec390919063ffffffff16565b600c8190555050610596565b60006105658383610e7990919063ffffffff16565b9050600c5481101561058b5761058681600c54610e7990919063ffffffff16565b61058e565b60005b600c81905550505b61059e610f4b565b600c5411156105f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061371f6029913960400191505060405180910390fd5b505b5050005b34801561060a57600080fd5b50610613610fba565b6040518082815260200191505060405180910390f35b34801561063557600080fd5b5061063e610fd8565b6040518082815260200191505060405180910390f35b34801561066057600080fd5b50610669611013565b6040518082815260200191505060405180910390f35b34801561068b57600080fd5b5061069461105a565b6040518082815260200191505060405180910390f35b3480156106b657600080fd5b506106bf611078565b005b3480156106cd57600080fd5b506106d6611345565b60405180821515815260200191505060405180910390f35b3480156106fa57600080fd5b50610703611358565b6040518082815260200191505060405180910390f35b34801561072557600080fd5b5061072e61135e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561076657600080fd5b5061076f611384565b60405180821515815260200191505060405180910390f35b34801561079357600080fd5b5061079c611397565b6040518082815260200191505060405180910390f35b3480156107be57600080fd5b506107c7610f4b565b6040518082815260200191505060405180910390f35b3480156107e957600080fd5b506107f261139d565b6040518082815260200191505060405180910390f35b34801561081457600080fd5b5061081d6113a3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561085557600080fd5b5061085e6113c9565b6040518082815260200191505060405180910390f35b34801561088057600080fd5b50610889611483565b005b34801561089757600080fd5b506108a0611731565b005b3480156108ae57600080fd5b506108b76118b0565b6040518082815260200191505060405180910390f35b3480156108d957600080fd5b506108e26118b6565b6040518082815260200191505060405180910390f35b34801561090457600080fd5b5061090d6118f2565b6040518082815260200191505060405180910390f35b34801561092f57600080fd5b506109386118f8565b005b34801561094657600080fd5b5061094f611b3a565b6040518082600281111561095f57fe5b815260200191505060405180910390f35b34801561097c57600080fd5b50610985611b4d565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156109bd57600080fd5b506109c6611b76565b6040518082815260200191505060405180910390f35b3480156109e857600080fd5b506109f1611bd4565b6040518082815260200191505060405180910390f35b348015610a1357600080fd5b50610a4060048036036020811015610a2a57600080fd5b8101908080359060200190929190505050611bda565b005b348015610a4e57600080fd5b50610a57611e55565b6040518082815260200191505060405180910390f35b348015610a7957600080fd5b50610a82611e78565b005b348015610a9057600080fd5b50610a996121d5565b6040518082815260200191505060405180910390f35b348015610abb57600080fd5b50610ba86004803603610160811015610ad357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff1690602001909291905050506121f3565b005b348015610bb657600080fd5b50610bbf610d64565b6040518082815260200191505060405180910390f35b348015610be157600080fd5b50610c2460048036036020811015610bf857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061221b565b005b348015610c3257600080fd5b50610c3b6122e8565b6040518082815260200191505060405180910390f35b348015610c5d57600080fd5b50610c666122f0565b6040518082815260200191505060405180910390f35b348015610c8857600080fd5b50610c916122f6565b6040518082815260200191505060405180910390f35b348015610cb357600080fd5b50610cbc6122fc565b6040518082815260200191505060405180910390f35b348015610cde57600080fd5b50610d2160048036036020811015610cf557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061231e565b005b348015610d2f57600080fd5b50610d38612522565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b8101908080519060200190929190505050905090565b6060610e7183836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b6000610ebb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612560565b905092915050565b600080828401905083811015610f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600280811115610f5957fe5b600960009054906101000a900460ff166002811115610f7457fe5b1415610f84576003549050610fb7565b6000600854118015610f9e5750600854610f9c6122e8565b105b15610fac5760009050610fb7565b610fb4611b76565b90505b90565b6000610fd360065460035461262090919063ffffffff16565b905090565b600061100e6001611000610fea611e55565b610ff26118b6565b61262090919063ffffffff16565b610ec390919063ffffffff16565b905090565b60008061101e610d64565b9050600061102a6121d5565b905080821115611050576110478183610e7990919063ffffffff16565b92505050611057565b6000925050505b90565b6000611073600454600554610e7990919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111a557600080fd5b505afa1580156111b9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156111e357600080fd5b810190808051604051939291908464010000000082111561120357600080fd5b8382019150602082018581111561121957600080fd5b825186602082028301116401000000008211171561123657600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561126d578082015181840152602081019050611252565b50505050905001604052505050905060005b81518110156113155761130882828151811061129757fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061127f565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806007541180156113e457506007546113e26122e8565b105b156113f25760009050611480565b600160028111156113ff57fe5b600960009054906101000a900460ff16600281111561141a57fe5b14801561142957506000600854115b801561143d575060085461143b6122e8565b105b1561144b5760009050611480565b6000611469600a5461145b611b76565b610e7990919063ffffffff16565b905061147c611476610d64565b8261282f565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611546576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115b057600080fd5b505afa1580156115c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156115ee57600080fd5b810190808051604051939291908464010000000082111561160e57600080fd5b8382019150602082018581111561162457600080fd5b825186602082028301116401000000008211171561164157600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561167857808201518184015260208101905061165d565b50505050905001604052505050905060005b8151811015611701576116f48282815181106116a257fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061168a565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b6000806118c16122e8565b905060045481116118d65760009150506118ef565b6118eb60045482610e7990919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146119bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006119c56113c9565b905060008111611a3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611a5281600a54610ec390919063ffffffff16565b600a81905550611ac7600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611b816122e8565b9050600454811015611b97576000915050611bd1565b600554811115611bac57600354915050611bd1565b611bcd611bb7610fba565b611bbf6122fc565b6128ea90919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008111611d13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b80611d1c611013565b1015611d73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806137696024913960400191505060405180910390fd5b611de2600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b6000611e73600654611e6561105a565b61262090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60016002811115611f4657fe5b600960009054906101000a900460ff166002811115611f6157fe5b14611fd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff1615151461205d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061207b61206a610f4b565b600354610e7990919063ffffffff16565b9050600081116120f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b6001600960016101000a81548160ff021916908315150217905550612162612119611b4d565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b60006121ee600a54600354610e7990919063ffffffff16565b905090565b6122058a8a8a8a8a8a8a8a8a8a612970565b61220e8b612ff1565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146122dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6122e581612ff1565b50565b600042905090565b600c5481565b60075481565b6000612319600161230b610fd8565b610e7990919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136d36026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606061255784846000856131d5565b90509392505050565b600083831115829061260d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156125d25780820151818401526020810190506125b7565b50505050905090810190601f1680156125ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600061266283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061337e565b905092915050565b6000811480612738575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156126fb57600080fd5b505afa15801561270f573d6000803e3d6000fd5b505050506040513d602081101561272557600080fd5b8101908080519060200190929190505050145b61278d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806137e16036913960400191505060405180910390fd5b61282a8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b600081831061283e5781612840565b825b905092915050565b6128e58363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b6000808314156128fd576000905061296a565b600082840290508284828161290e57fe5b0414612965576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806137486021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156129f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612a96576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612bdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b60008711612c52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b6000861415612cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610612d3e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015612db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b60006002811115612dc257fe5b816002811115612dce57fe5b1415612e42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310612e9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061378d602a913960400191505060405180910390fd5b848210612ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806136b16022913960400191505060405180910390fd5b6001600960026101000a81548160ff021916908315150217905550612f168a613533565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff02191690836002811115612fe057fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613094576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61309d816135d1565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015613230576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136f96026913960400191505060405180910390fd5b613239856135d1565b6132ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106132fb57805182526020820191506020810190506020830392506132d8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461335d576040519150601f19603f3d011682016040523d82523d6000602084013e613362565b606091505b50915091506133728282866135e4565b92505050949350505050565b6000808311829061342a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156133ef5780820151818401526020810190506133d4565b50505050905090810190601f16801561341c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161343657fe5b049050809150509392505050565b60606134a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b905060008151111561352e578080602001905160208110156134c757600080fd5b810190808051906020019092919050505061352d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806137b7602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b606083156135f4578290506136a9565b6000835111156136075782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561366e578082015181840152602081019050613653565b50505050905090810190601f16801561369b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220568a2fe9dc70706737374723ca77697bf133d14dda9ad40e2b8f6f167a7ec56264736f6c63430007030033", + "deployedBytecode": "0x60806040526004361061021e5760003560e01c806386d00e0211610123578063bc0163c1116100ab578063e8dda6f51161006f578063e8dda6f514610c51578063e97d87d514610c7c578063ebbab99214610ca7578063f2fde38b14610cd2578063fc0c546a14610d235761021f565b8063bc0163c114610a84578063bd896dcb14610aaf578063ce845d1d14610baa578063d0ebdbe714610bd5578063d18e81b314610c265761021f565b806391f7cfb9116100f257806391f7cfb9146109b1578063a4caeb42146109dc578063b0d1818c14610a07578063b470aade14610a42578063b6549f7514610a6d5761021f565b806386d00e02146108f857806386d1a69f14610923578063872a78101461093a5780638da5cb5b146109705761021f565b8063398057a3116101a65780635b940081116101755780635b9400811461084957806360e7994414610874578063715018a61461088b57806378e97925146108a25780637bdf05af146108cd5761021f565b8063398057a31461078757806344b1231f146107b257806345d30a17146107dd578063481c6a75146108085761021f565b80632a627814116101ed5780632a627814146106aa5780632bc9ed02146106c15780633197cbb6146106ee57806338af3eed14610719578063392e53cd1461075a5761021f565b8063029c6c9f146105fe57806306040618146106295780630dff24d5146106545780630fb5a6b41461067f5761021f565b5b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102e2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f556e617574686f72697a65642063616c6c65720000000000000000000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b815260040180827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060206040518083038186803b15801561039a57600080fd5b505afa1580156103ae573d6000803e3d6000fd5b505050506040513d60208110156103c457600080fd5b81019080805190602001909291905050509050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561047a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f556e617574686f72697a65642066756e6374696f6e000000000000000000000081525060200191505060405180910390fd5b6000610484610d64565b90506104d5826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610e2f565b50600160028111156104e357fe5b600960009054906101000a900460ff1660028111156104fe57fe5b14156105fa57600061050e610d64565b90508181101561055057600061052d8284610e7990919063ffffffff16565b905061054481600c54610ec390919063ffffffff16565b600c8190555050610596565b60006105658383610e7990919063ffffffff16565b9050600c5481101561058b5761058681600c54610e7990919063ffffffff16565b61058e565b60005b600c81905550505b61059e610f4b565b600c5411156105f8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061371f6029913960400191505060405180910390fd5b505b5050005b34801561060a57600080fd5b50610613610fba565b6040518082815260200191505060405180910390f35b34801561063557600080fd5b5061063e610fd8565b6040518082815260200191505060405180910390f35b34801561066057600080fd5b50610669611013565b6040518082815260200191505060405180910390f35b34801561068b57600080fd5b5061069461105a565b6040518082815260200191505060405180910390f35b3480156106b657600080fd5b506106bf611078565b005b3480156106cd57600080fd5b506106d6611345565b60405180821515815260200191505060405180910390f35b3480156106fa57600080fd5b50610703611358565b6040518082815260200191505060405180910390f35b34801561072557600080fd5b5061072e61135e565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561076657600080fd5b5061076f611384565b60405180821515815260200191505060405180910390f35b34801561079357600080fd5b5061079c611397565b6040518082815260200191505060405180910390f35b3480156107be57600080fd5b506107c7610f4b565b6040518082815260200191505060405180910390f35b3480156107e957600080fd5b506107f261139d565b6040518082815260200191505060405180910390f35b34801561081457600080fd5b5061081d6113a3565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561085557600080fd5b5061085e6113c9565b6040518082815260200191505060405180910390f35b34801561088057600080fd5b50610889611483565b005b34801561089757600080fd5b506108a0611731565b005b3480156108ae57600080fd5b506108b76118b0565b6040518082815260200191505060405180910390f35b3480156108d957600080fd5b506108e26118b6565b6040518082815260200191505060405180910390f35b34801561090457600080fd5b5061090d6118f2565b6040518082815260200191505060405180910390f35b34801561092f57600080fd5b506109386118f8565b005b34801561094657600080fd5b5061094f611b3a565b6040518082600281111561095f57fe5b815260200191505060405180910390f35b34801561097c57600080fd5b50610985611b4d565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156109bd57600080fd5b506109c6611b76565b6040518082815260200191505060405180910390f35b3480156109e857600080fd5b506109f1611bd4565b6040518082815260200191505060405180910390f35b348015610a1357600080fd5b50610a4060048036036020811015610a2a57600080fd5b8101908080359060200190929190505050611bda565b005b348015610a4e57600080fd5b50610a57611e55565b6040518082815260200191505060405180910390f35b348015610a7957600080fd5b50610a82611e78565b005b348015610a9057600080fd5b50610a996121d5565b6040518082815260200191505060405180910390f35b348015610abb57600080fd5b50610ba86004803603610160811015610ad357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190803590602001909291908035906020019092919080359060200190929190803560ff1690602001909291905050506121f3565b005b348015610bb657600080fd5b50610bbf610d64565b6040518082815260200191505060405180910390f35b348015610be157600080fd5b50610c2460048036036020811015610bf857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061221b565b005b348015610c3257600080fd5b50610c3b6122e8565b6040518082815260200191505060405180910390f35b348015610c5d57600080fd5b50610c666122f0565b6040518082815260200191505060405180910390f35b348015610c8857600080fd5b50610c916122f6565b6040518082815260200191505060405180910390f35b348015610cb357600080fd5b50610cbc6122fc565b6040518082815260200191505060405180910390f35b348015610cde57600080fd5b50610d2160048036036020811015610cf557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919050505061231e565b005b348015610d2f57600080fd5b50610d38612522565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015610def57600080fd5b505afa158015610e03573d6000803e3d6000fd5b505050506040513d6020811015610e1957600080fd5b8101908080519060200190929190505050905090565b6060610e7183836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b6000610ebb83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612560565b905092915050565b600080828401905083811015610f41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b6000600280811115610f5957fe5b600960009054906101000a900460ff166002811115610f7457fe5b1415610f84576003549050610fb7565b6000600854118015610f9e5750600854610f9c6122e8565b105b15610fac5760009050610fb7565b610fb4611b76565b90505b90565b6000610fd360065460035461262090919063ffffffff16565b905090565b600061100e6001611000610fea611e55565b610ff26118b6565b61262090919063ffffffff16565b610ec390919063ffffffff16565b905090565b60008061101e610d64565b9050600061102a6121d5565b905080821115611050576110478183610e7990919063ffffffff16565b92505050611057565b6000925050505b90565b6000611073600454600554610e7990919063ffffffff16565b905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461113b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111a557600080fd5b505afa1580156111b9573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156111e357600080fd5b810190808051604051939291908464010000000082111561120357600080fd5b8382019150602082018581111561121957600080fd5b825186602082028301116401000000008211171561123657600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561126d578082015181840152602081019050611252565b50505050905001604052505050905060005b81518110156113155761130882828151811061129757fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061127f565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b600960019054906101000a900460ff1681565b60055481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600960029054906101000a900460ff1681565b60035481565b600a5481565b600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000806007541180156113e457506007546113e26122e8565b105b156113f25760009050611480565b600160028111156113ff57fe5b600960009054906101000a900460ff16600281111561141a57fe5b14801561142957506000600854115b801561143d575060085461143b6122e8565b105b1561144b5760009050611480565b6000611469600a5461145b611b76565b610e7990919063ffffffff16565b905061147c611476610d64565b8261282f565b9150505b90565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611546576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b6060600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115b057600080fd5b505afa1580156115c4573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525060208110156115ee57600080fd5b810190808051604051939291908464010000000082111561160e57600080fd5b8382019150602082018581111561162457600080fd5b825186602082028301116401000000008211171561164157600080fd5b8083526020830192505050908051906020019060200280838360005b8381101561167857808201518184015260208101905061165d565b50505050905001604052505050905060005b8151811015611701576116f48282815181106116a257fe5b60200260200101516000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661266a9092919063ffffffff16565b808060010191505061168a565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117f2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60045481565b6000806118c16122e8565b905060045481116118d65760009150506118ef565b6118eb60045482610e7990919063ffffffff16565b9150505b90565b60085481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146119bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60006119c56113c9565b905060008111611a3d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e74000081525060200191505060405180910390fd5b611a5281600a54610ec390919063ffffffff16565b600a81905550611ac7600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df93179826040518082815260200191505060405180910390a250565b600960009054906101000a900460ff1681565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611b816122e8565b9050600454811015611b97576000915050611bd1565b600554811115611bac57600354915050611bd1565b611bcd611bb7610fba565b611bbf6122fc565b6128ea90919063ffffffff16565b9150505b90565b60065481565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c9d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260058152602001807f216175746800000000000000000000000000000000000000000000000000000081525060200191505060405180910390fd5b60008111611d13576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f416d6f756e742063616e6e6f74206265207a65726f000000000000000000000081525060200191505060405180910390fd5b80611d1c611013565b1015611d73576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260248152602001806137696024913960400191505060405180910390fd5b611de2600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040518082815260200191505060405180910390a250565b6000611e73600654611e6561105a565b61262090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611f39576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60016002811115611f4657fe5b600960009054906101000a900460ff166002811115611f6157fe5b14611fd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f436f6e7472616374206973206e6f6e2d7265766f6361626c650000000000000081525060200191505060405180910390fd5b60001515600960019054906101000a900460ff1615151461205d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600f8152602001807f416c7265616479207265766f6b6564000000000000000000000000000000000081525060200191505060405180910390fd5b600061207b61206a610f4b565b600354610e7990919063ffffffff16565b9050600081116120f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4e6f20617661696c61626c6520756e76657374656420616d6f756e740000000081525060200191505060405180910390fd5b6001600960016101000a81548160ff021916908315150217905550612162612119611b4d565b82600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166128489092919063ffffffff16565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040518082815260200191505060405180910390a250565b60006121ee600a54600354610e7990919063ffffffff16565b905090565b6122058a8a8a8a8a8a8a8a8a8a612970565b61220e8b612ff1565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146122dc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6122e581612ff1565b50565b600042905090565b600c5481565b60075481565b6000612319600161230b610fd8565b610e7990919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136d36026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606061255784846000856131d5565b90509392505050565b600083831115829061260d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156125d25780820151818401526020810190506125b7565b50505050905090810190601f1680156125ff5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600061266283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061337e565b905092915050565b6000811480612738575060008373ffffffffffffffffffffffffffffffffffffffff1663dd62ed3e30856040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1681526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060206040518083038186803b1580156126fb57600080fd5b505afa15801561270f573d6000803e3d6000fd5b505050506040513d602081101561272557600080fd5b8101908080519060200190929190505050145b61278d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806137e16036913960400191505060405180910390fd5b61282a8363095ea7b360e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b600081831061283e5781612840565b825b905092915050565b6128e58363a9059cbb60e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050613444565b505050565b6000808314156128fd576000905061296a565b600082840290508284828161290e57fe5b0414612965576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806137486021913960400191505060405180910390fd5b809150505b92915050565b600960029054906101000a900460ff16156129f3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f416c726561647920696e697469616c697a65640000000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff161415612a96576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f4f776e65722063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff161415612b39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f42656e65666963696172792063616e6e6f74206265207a65726f00000000000081525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff161415612bdc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260148152602001807f546f6b656e2063616e6e6f74206265207a65726f00000000000000000000000081525060200191505060405180910390fd5b60008711612c52576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f00000081525060200191505060405180910390fd5b6000861415612cc9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260168152602001807f53746172742074696d65206d757374206265207365740000000000000000000081525060200191505060405180910390fd5b848610612d3e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260158152602001807f53746172742074696d65203e20656e642074696d65000000000000000000000081525060200191505060405180910390fd5b6001841015612db5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d0081525060200191505060405180910390fd5b60006002811115612dc257fe5b816002811115612dce57fe5b1415612e42576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f4d757374207365742061207265766f636162696c697479206f7074696f6e000081525060200191505060405180910390fd5b848310612e9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a81526020018061378d602a913960400191505060405180910390fd5b848210612ef2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806136b16022913960400191505060405180910390fd5b6001600960026101000a81548160ff021916908315150217905550612f168a613533565b88600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555086600381905550856004819055508460058190555083600681905550826007819055508160088190555080600960006101000a81548160ff02191690836002811115612fe057fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415613094576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260178152602001807f4d616e616765722063616e6e6f7420626520656d70747900000000000000000081525060200191505060405180910390fd5b61309d816135d1565b61310f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f4d616e61676572206d757374206265206120636f6e747261637400000000000081525060200191505060405180910390fd5b6000600b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081600b60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015613230576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806136f96026913960400191505060405180910390fd5b613239856135d1565b6132ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b602083106132fb57805182526020820191506020810190506020830392506132d8565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d806000811461335d576040519150601f19603f3d011682016040523d82523d6000602084013e613362565b606091505b50915091506133728282866135e4565b92505050949350505050565b6000808311829061342a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156133ef5780820151818401526020810190506133d4565b50505050905090810190601f16801561341c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161343657fe5b049050809150509392505050565b60606134a6826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b905060008151111561352e578080602001905160208110156134c757600080fd5b810190808051906020019092919050505061352d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a8152602001806137b7602a913960400191505060405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b606083156135f4578290506136a9565b6000835111156136075782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561366e578082015181840152602081019050613653565b50505050905090810190601f16801561369b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b939250505056fe436c6966662074696d65206d757374206265206265666f726520656e642074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c43616e6e6f7420757365206d6f726520746f6b656e73207468616e2076657374656420616d6f756e74536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77416d6f756e7420726571756573746564203e20737572706c757320617661696c61626c6552656c656173652073746172742074696d65206d757374206265206265666f726520656e642074696d655361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a2646970667358221220568a2fe9dc70706737374723ca77697bf133d14dda9ad40e2b8f6f167a7ec56264736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule and takes into account already released tokens", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 4371, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 2351, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "1", + "type": "t_contract(IERC20)908" + }, + { + "astId": 2353, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "2", + "type": "t_address" + }, + { + "astId": 2355, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 2357, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "4", + "type": "t_uint256" + }, + { + "astId": 2359, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "5", + "type": "t_uint256" + }, + { + "astId": 2361, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "6", + "type": "t_uint256" + }, + { + "astId": 2363, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "7", + "type": "t_uint256" + }, + { + "astId": 2365, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "8", + "type": "t_uint256" + }, + { + "astId": 2367, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "9", + "type": "t_enum(Revocability)4048" + }, + { + "astId": 2369, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2371, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "9", + "type": "t_bool" + }, + { + "astId": 2373, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "10", + "type": "t_uint256" + }, + { + "astId": 3708, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "11", + "type": "t_contract(IGraphTokenLockManager)4230" + }, + { + "astId": 3710, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "12", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)908": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)4230": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)4048": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/rinkeby/GraphTokenMock.json b/packages/token-distribution/deployments/rinkeby/GraphTokenMock.json new file mode 100644 index 000000000..b65e67b21 --- /dev/null +++ b/packages/token-distribution/deployments/rinkeby/GraphTokenMock.json @@ -0,0 +1,552 @@ +{ + "address": "0xB0a7bC0e6b51db8Cfda3f80904c8E35259F1abDb", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialSupply", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_mintTo", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xc6ebb0d9652e8f9cdccc558c1769897a4b6974c44c45edfce41eea79d38d96cd", + "receipt": { + "to": null, + "from": "0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9", + "contractAddress": "0xB0a7bC0e6b51db8Cfda3f80904c8E35259F1abDb", + "transactionIndex": 0, + "gasUsed": "1390294", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000040000000000000008000000000000000000000000000000000000008000000000001000000000000080000000000000000000000020000000000000000000800000000000000000000000010000000400000000000020000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000020000000000000000000000000000004000000000000000000000000000000000000", + "blockHash": "0xd6c552379d4aa84f79f52045e15b53498e903da2a2f2a85b72e10e3dd633a6be", + "transactionHash": "0xc6ebb0d9652e8f9cdccc558c1769897a4b6974c44c45edfce41eea79d38d96cd", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 7727637, + "transactionHash": "0xc6ebb0d9652e8f9cdccc558c1769897a4b6974c44c45edfce41eea79d38d96cd", + "address": "0xB0a7bC0e6b51db8Cfda3f80904c8E35259F1abDb", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000023d1b1823e6cb5229137424f88c70fda1539f1f9" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0xd6c552379d4aa84f79f52045e15b53498e903da2a2f2a85b72e10e3dd633a6be" + }, + { + "transactionIndex": 0, + "blockNumber": 7727637, + "transactionHash": "0xc6ebb0d9652e8f9cdccc558c1769897a4b6974c44c45edfce41eea79d38d96cd", + "address": "0xB0a7bC0e6b51db8Cfda3f80904c8E35259F1abDb", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000023d1b1823e6cb5229137424f88c70fda1539f1f9" + ], + "data": "0x0000000000000000000000000000000000000000204fce5e3e25026110000000", + "logIndex": 1, + "blockHash": "0xd6c552379d4aa84f79f52045e15b53498e903da2a2f2a85b72e10e3dd633a6be" + } + ], + "blockNumber": 7727637, + "cumulativeGasUsed": "1390294", + "status": 1, + "byzantium": true + }, + "args": [ + "10000000000000000000000000000", + "0x23D1B1823e6Cb5229137424f88C70fdA1539F1F9" + ], + "solcInputHash": "a72ab6278ade6c5c10115f7be2c555c9", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_initialSupply\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"_mintTo\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"constructor\":{\"details\":\"Contract Constructor.\",\"params\":{\"_initialSupply\":\"Initial supply\"}},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"}},\"title\":\"Graph Token Mock\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenMock.sol\":\"GraphTokenMock\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/GSN/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../GSN/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xf7c39c7e6d06ed3bda90cfefbcbf2ddc32c599c3d6721746546ad64946efccaa\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return sub(a, b, \\\"SafeMath: subtraction overflow\\\");\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n uint256 c = a - b;\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) {\\n return 0;\\n }\\n\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return div(a, b, \\\"SafeMath: division by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n uint256 c = a / b;\\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\\n\\n return c;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return mod(a, b, \\\"SafeMath: modulo by zero\\\");\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * Reverts with custom message when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b != 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0x3b21f2c8d626de3b9925ae33e972d8bf5c8b1bffb3f4ee94daeed7d0679036e6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../../GSN/Context.sol\\\";\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin guidelines: functions revert instead\\n * of returning `false` on failure. This behavior is nonetheless conventional\\n * and does not conflict with the expectations of ERC20 applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20 {\\n using SafeMath for uint256;\\n\\n mapping (address => uint256) private _balances;\\n\\n mapping (address => mapping (address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n uint8 private _decimals;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\\n * a default value of 18.\\n *\\n * To select a different value for {decimals}, use {_setupDecimals}.\\n *\\n * All three of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor (string memory name_, string memory symbol_) public {\\n _name = name_;\\n _symbol = symbol_;\\n _decimals = 18;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\\n * called.\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view returns (uint8) {\\n return _decimals;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `recipient` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(_msgSender(), recipient, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n _approve(_msgSender(), spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * Requirements:\\n *\\n * - `sender` and `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``sender``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\\n _transfer(sender, recipient, amount);\\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \\\"ERC20: transfer amount exceeds allowance\\\"));\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \\\"ERC20: decreased allowance below zero\\\"));\\n return true;\\n }\\n\\n /**\\n * @dev Moves tokens `amount` from `sender` to `recipient`.\\n *\\n * This is internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `sender` cannot be the zero address.\\n * - `recipient` cannot be the zero address.\\n * - `sender` must have a balance of at least `amount`.\\n */\\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\\n require(sender != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(recipient != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(sender, recipient, amount);\\n\\n _balances[sender] = _balances[sender].sub(amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n _balances[recipient] = _balances[recipient].add(amount);\\n emit Transfer(sender, recipient, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply = _totalSupply.add(amount);\\n _balances[account] = _balances[account].add(amount);\\n emit Transfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n _balances[account] = _balances[account].sub(amount, \\\"ERC20: burn amount exceeds balance\\\");\\n _totalSupply = _totalSupply.sub(amount);\\n emit Transfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(address owner, address spender, uint256 amount) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Sets {decimals} to a value other than the default one of 18.\\n *\\n * WARNING: This function should only be called from the constructor. Most\\n * applications that interact with token contracts will not expect\\n * {decimals} to ever change, and may work incorrectly if it does.\\n */\\n function _setupDecimals(uint8 decimals_) internal {\\n _decimals = decimals_;\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be to transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\\n}\\n\",\"keccak256\":\"0xcbd85c86627a47fd939f1f4ee3ba626575ff2a182e1804b29f5136394449b538\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"contracts/GraphTokenMock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\n/**\\n * @title Graph Token Mock\\n */\\ncontract GraphTokenMock is Ownable, ERC20 {\\n /**\\n * @dev Contract Constructor.\\n * @param _initialSupply Initial supply\\n */\\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\\\"Graph Token Mock\\\", \\\"GRT-Mock\\\") {\\n // Deploy to mint address\\n _mint(_mintTo, _initialSupply);\\n }\\n}\\n\",\"keccak256\":\"0x23c200e0c4d7169a51aed2e1571fd0d7954b24fa93faa662d02b535ddbf5b3bf\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001a9038038062001a90833981810160405260408110156200003757600080fd5b8101908080519060200190929190805190602001909291905050506040518060400160405280601081526020017f477261706820546f6b656e204d6f636b000000000000000000000000000000008152506040518060400160405280600881526020017f4752542d4d6f636b0000000000000000000000000000000000000000000000008152506000620000d0620001d860201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3508160049080519060200190620001869291906200044e565b5080600590805190602001906200019f9291906200044e565b506012600660006101000a81548160ff021916908360ff1602179055505050620001d08183620001e060201b60201c565b5050620004f4565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141562000284576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b6200029860008383620003c060201b60201c565b620002b481600354620003c560201b62000e1e1790919060201c565b6003819055506200031381600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054620003c560201b62000e1e1790919060201c565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b505050565b60008082840190508381101562000444576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200049157805160ff1916838001178555620004c2565b82800160010185558215620004c2579182015b82811115620004c1578251825591602001919060010190620004a4565b5b509050620004d19190620004d5565b5090565b5b80821115620004f0576000816000905550600101620004d6565b5090565b61158c80620005046000396000f3fe608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063715018a61161008c578063a457c2d711610066578063a457c2d714610416578063a9059cbb1461047a578063dd62ed3e146104de578063f2fde38b14610556576100ea565b8063715018a6146103555780638da5cb5b1461035f57806395d89b4114610393576100ea565b806323b872dd116100c857806323b872dd146101f4578063313ce56714610278578063395093511461029957806370a08231146102fd576100ea565b806306fdde03146100ef578063095ea7b31461017257806318160ddd146101d6575b600080fd5b6100f761059a565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013757808201518184015260208101905061011c565b50505050905090810190601f1680156101645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101be6004803603604081101561018857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061063c565b60405180821515815260200191505060405180910390f35b6101de61065a565b6040518082815260200191505060405180910390f35b6102606004803603606081101561020a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610664565b60405180821515815260200191505060405180910390f35b61028061073d565b604051808260ff16815260200191505060405180910390f35b6102e5600480360360408110156102af57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610754565b60405180821515815260200191505060405180910390f35b61033f6004803603602081101561031357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610807565b6040518082815260200191505060405180910390f35b61035d610850565b005b6103676109d6565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61039b6109ff565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103db5780820151818401526020810190506103c0565b50505050905090810190601f1680156104085780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104626004803603604081101561042c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610aa1565b60405180821515815260200191505060405180910390f35b6104c66004803603604081101561049057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b6e565b60405180821515815260200191505060405180910390f35b610540600480360360408110156104f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b8c565b6040518082815260200191505060405180910390f35b6105986004803603602081101561056c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c13565b005b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106325780601f1061060757610100808354040283529160200191610632565b820191906000526020600020905b81548152906001019060200180831161061557829003601f168201915b5050505050905090565b6000610650610649610ea6565b8484610eae565b6001905092915050565b6000600354905090565b60006106718484846110a5565b6107328461067d610ea6565b61072d856040518060600160405280602881526020016114c160289139600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006106e3610ea6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136a9092919063ffffffff16565b610eae565b600190509392505050565b6000600660009054906101000a900460ff16905090565b60006107fd610761610ea6565b846107f88560026000610772610ea6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e1e90919063ffffffff16565b610eae565b6001905092915050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610858610ea6565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610918576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a975780601f10610a6c57610100808354040283529160200191610a97565b820191906000526020600020905b815481529060010190602001808311610a7a57829003601f168201915b5050505050905090565b6000610b64610aae610ea6565b84610b5f856040518060600160405280602581526020016115326025913960026000610ad8610ea6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136a9092919063ffffffff16565b610eae565b6001905092915050565b6000610b82610b7b610ea6565b84846110a5565b6001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610c1b610ea6565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610cdb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610d61576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806114536026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080828401905083811015610e9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061150e6024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610fba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806114796022913960400191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561112b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806114e96025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156111b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806114306023913960400191505060405180910390fd5b6111bc83838361142a565b6112288160405180606001604052806026815260200161149b60269139600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136a9092919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506112bd81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e1e90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290611417576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156113dc5780820151818401526020810190506113c1565b50505050905090810190601f1680156114095780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220f69e6542f5ac170217d7f1aaeaf175ae967c01348ec113f5c49cd2dacad8eec264736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100ea5760003560e01c8063715018a61161008c578063a457c2d711610066578063a457c2d714610416578063a9059cbb1461047a578063dd62ed3e146104de578063f2fde38b14610556576100ea565b8063715018a6146103555780638da5cb5b1461035f57806395d89b4114610393576100ea565b806323b872dd116100c857806323b872dd146101f4578063313ce56714610278578063395093511461029957806370a08231146102fd576100ea565b806306fdde03146100ef578063095ea7b31461017257806318160ddd146101d6575b600080fd5b6100f761059a565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561013757808201518184015260208101905061011c565b50505050905090810190601f1680156101645780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101be6004803603604081101561018857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061063c565b60405180821515815260200191505060405180910390f35b6101de61065a565b6040518082815260200191505060405180910390f35b6102606004803603606081101561020a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610664565b60405180821515815260200191505060405180910390f35b61028061073d565b604051808260ff16815260200191505060405180910390f35b6102e5600480360360408110156102af57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610754565b60405180821515815260200191505060405180910390f35b61033f6004803603602081101561031357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610807565b6040518082815260200191505060405180910390f35b61035d610850565b005b6103676109d6565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61039b6109ff565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103db5780820151818401526020810190506103c0565b50505050905090810190601f1680156104085780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104626004803603604081101561042c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610aa1565b60405180821515815260200191505060405180910390f35b6104c66004803603604081101561049057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610b6e565b60405180821515815260200191505060405180910390f35b610540600480360360408110156104f457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610b8c565b6040518082815260200191505060405180910390f35b6105986004803603602081101561056c57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c13565b005b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156106325780601f1061060757610100808354040283529160200191610632565b820191906000526020600020905b81548152906001019060200180831161061557829003601f168201915b5050505050905090565b6000610650610649610ea6565b8484610eae565b6001905092915050565b6000600354905090565b60006106718484846110a5565b6107328461067d610ea6565b61072d856040518060600160405280602881526020016114c160289139600260008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006106e3610ea6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136a9092919063ffffffff16565b610eae565b600190509392505050565b6000600660009054906101000a900460ff16905090565b60006107fd610761610ea6565b846107f88560026000610772610ea6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e1e90919063ffffffff16565b610eae565b6001905092915050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b610858610ea6565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610918576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a975780601f10610a6c57610100808354040283529160200191610a97565b820191906000526020600020905b815481529060010190602001808311610a7a57829003601f168201915b5050505050905090565b6000610b64610aae610ea6565b84610b5f856040518060600160405280602581526020016115326025913960026000610ad8610ea6565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136a9092919063ffffffff16565b610eae565b6001905092915050565b6000610b82610b7b610ea6565b84846110a5565b6001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b610c1b610ea6565b73ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610cdb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415610d61576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806114536026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600080828401905083811015610e9c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415610f34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602481526020018061150e6024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415610fba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806114796022913960400191505060405180910390fd5b80600260008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561112b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001806114e96025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156111b1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001806114306023913960400191505060405180910390fd5b6111bc83838361142a565b6112288160405180606001604052806026815260200161149b60269139600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205461136a9092919063ffffffff16565b600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506112bd81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054610e1e90919063ffffffff16565b600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b6000838311158290611417576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156113dc5780820151818401526020810190506113c1565b50505050905090810190601f1680156114095780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b50505056fe45524332303a207472616e7366657220746f20746865207a65726f20616464726573734f776e61626c653a206e6577206f776e657220697320746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa2646970667358221220f69e6542f5ac170217d7f1aaeaf175ae967c01348ec113f5c49cd2dacad8eec264736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "constructor": { + "details": "Contract Constructor.", + "params": { + "_initialSupply": "Initial supply" + } + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is called. NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for ``sender``'s tokens of at least `amount`." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + }, + "title": "Graph Token Mock", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 30, + "contract": "contracts/GraphTokenMock.sol:GraphTokenMock", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 344, + "contract": "contracts/GraphTokenMock.sol:GraphTokenMock", + "label": "_balances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 350, + "contract": "contracts/GraphTokenMock.sol:GraphTokenMock", + "label": "_allowances", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 352, + "contract": "contracts/GraphTokenMock.sol:GraphTokenMock", + "label": "_totalSupply", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 354, + "contract": "contracts/GraphTokenMock.sol:GraphTokenMock", + "label": "_name", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + }, + { + "astId": 356, + "contract": "contracts/GraphTokenMock.sol:GraphTokenMock", + "label": "_symbol", + "offset": 0, + "slot": "5", + "type": "t_string_storage" + }, + { + "astId": 358, + "contract": "contracts/GraphTokenMock.sol:GraphTokenMock", + "label": "_decimals", + "offset": 0, + "slot": "6", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/rinkeby/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json b/packages/token-distribution/deployments/rinkeby/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json new file mode 100644 index 000000000..ee7330e86 --- /dev/null +++ b/packages/token-distribution/deployments/rinkeby/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json @@ -0,0 +1,98 @@ +{ + "language": "Solidity", + "sources": { + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../GSN/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction overflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/GSN/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n uint256 private constant MAX_UINT256 = 2**256 - 1;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) private {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], MAX_UINT256);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n token.safeApprove(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is Ownable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n uint256 public releasedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n Ownable.initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public override view returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public override view returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public override view returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public override view returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public override view returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public override view returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public override view returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public override view returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public override view returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public override view returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public override view returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public override view returns (uint256) {\n return managedAmount.sub(releasedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public override view returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability { NotSet, Enabled, Disabled }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/StakingMock.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/Stakes.sol": { + "content": "pragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(\n Stakes.Indexer storage stake,\n uint256 _tokens,\n uint256 _period\n ) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(Stakes.Indexer memory stake, uint256 _delegatedCapacity)\n internal\n pure\n returns (uint256)\n {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../GSN/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "contracts/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @dev Contract Constructor.\n * @param _initialSupply Initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Create2.sol\";\n\n// Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n// Based on https://eips.ethereum.org/EIPS/eip-1167\ncontract MinimalProxyFactory is Ownable {\n // -- Events --\n\n event ProxyCreated(address indexed proxy);\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(bytes32 _salt, address _implementation) external view returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), address(this));\n }\n\n /**\n * @notice Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(\n bytes32 _salt,\n address _implementation,\n bytes memory _data\n ) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @notice Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint256(_data));\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 private _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSignature(\n \"initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\",\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets)\n external\n override\n onlyOwner\n {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solium-disable-next-line security/no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(value)));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint256(_at(set._inner, index)));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n * \n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n Ownable.initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/sepolia/.chainId b/packages/token-distribution/deployments/sepolia/.chainId new file mode 100644 index 000000000..bd8d1cd44 --- /dev/null +++ b/packages/token-distribution/deployments/sepolia/.chainId @@ -0,0 +1 @@ +11155111 \ No newline at end of file diff --git a/packages/token-distribution/deployments/sepolia/GraphTokenLockManager.json b/packages/token-distribution/deployments/sepolia/GraphTokenLockManager.json new file mode 100644 index 000000000..929ab3ff5 --- /dev/null +++ b/packages/token-distribution/deployments/sepolia/GraphTokenLockManager.json @@ -0,0 +1,969 @@ +{ + "address": "0x11682Df78472B8c533160E898f8D1b134AE1CE0D", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes4", + "name": "sigHash", + "type": "bytes4" + }, + { + "indexed": true, + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "signature", + "type": "string" + } + ], + "name": "FunctionCallAuth", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "masterCopy", + "type": "address" + } + ], + "name": "MasterCopyUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "allowed", + "type": "bool" + } + ], + "name": "TokenDestinationAllowed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "initHash", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "managedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "periods", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "vestingCliffTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum IGraphTokenLock.Revocability", + "name": "revocable", + "type": "uint8" + } + ], + "name": "TokenLockCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "addTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "name": "authFnCalls", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "createTokenLockWallet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "getAuthFunctionCallTarget", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenDestinations", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_sigHash", + "type": "bytes4" + } + ], + "name": "isAuthFunctionCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "isTokenDestination", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "masterCopy", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_dst", + "type": "address" + } + ], + "name": "removeTokenDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + }, + { + "internalType": "address", + "name": "_target", + "type": "address" + } + ], + "name": "setAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string[]", + "name": "_signatures", + "type": "string[]" + }, + { + "internalType": "address[]", + "name": "_targets", + "type": "address[]" + } + ], + "name": "setAuthFunctionCallMany", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterCopy", + "type": "address" + } + ], + "name": "setMasterCopy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "_signature", + "type": "string" + } + ], + "name": "unsetAuthFunctionCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x789ed81816498d4826ba8ef43a8f9396030694029fb331243388b1be4876e15a", + "receipt": { + "to": null, + "from": "0x559081D91F5Ff43dfE51A07C216F8E6893805B35", + "contractAddress": "0x11682Df78472B8c533160E898f8D1b134AE1CE0D", + "transactionIndex": 47, + "gasUsed": "3196993", + "logsBloom": "0x00000000000000000000000000000000000004000000000000801000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000400000000000000000020000000000000000000800000000000000000000000040000000400000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000200000000000000000000000000000000000000000010000000000020000020000000000000000000000000000000040000000000000000000000001000000000", + "blockHash": "0xe5a1b4cd80a8d1d3a9c3412055f36cc2b4c1a72d39ca9167eb5f0fbf3d6a5ae6", + "transactionHash": "0x789ed81816498d4826ba8ef43a8f9396030694029fb331243388b1be4876e15a", + "logs": [ + { + "transactionIndex": 47, + "blockNumber": 4570364, + "transactionHash": "0x789ed81816498d4826ba8ef43a8f9396030694029fb331243388b1be4876e15a", + "address": "0x11682Df78472B8c533160E898f8D1b134AE1CE0D", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000559081d91f5ff43dfe51a07c216f8e6893805b35" + ], + "data": "0x", + "logIndex": 134, + "blockHash": "0xe5a1b4cd80a8d1d3a9c3412055f36cc2b4c1a72d39ca9167eb5f0fbf3d6a5ae6" + }, + { + "transactionIndex": 47, + "blockNumber": 4570364, + "transactionHash": "0x789ed81816498d4826ba8ef43a8f9396030694029fb331243388b1be4876e15a", + "address": "0x11682Df78472B8c533160E898f8D1b134AE1CE0D", + "topics": [ + "0x30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de", + "0x000000000000000000000000d8a03c88984d5669d467ae72fbb21cd7ce6e08d4" + ], + "data": "0x", + "logIndex": 135, + "blockHash": "0xe5a1b4cd80a8d1d3a9c3412055f36cc2b4c1a72d39ca9167eb5f0fbf3d6a5ae6" + } + ], + "blockNumber": 4570364, + "cumulativeGasUsed": "14371490", + "status": 1, + "byzantium": true + }, + "args": [ + "0xCA59cCeb39bE1808d7aA607153f4A5062daF3a83", + "0xd8a03C88984d5669d467aE72Fbb21cD7Ce6E08D4" + ], + "solcInputHash": "095bd30babc75057be19228ca1fd7aa4", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"_graphToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"caller\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes4\",\"name\":\"sigHash\",\"type\":\"bytes4\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"signature\",\"type\":\"string\"}],\"name\":\"FunctionCallAuth\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"masterCopy\",\"type\":\"address\"}],\"name\":\"MasterCopyUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"proxy\",\"type\":\"address\"}],\"name\":\"ProxyCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"TokenDestinationAllowed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"contractAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"initHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"managedAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"periods\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"vestingCliffTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"revocable\",\"type\":\"uint8\"}],\"name\":\"TokenLockCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"addTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"name\":\"authFnCalls\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"createTokenLockWallet\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"getAuthFunctionCallTarget\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_deployer\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_salt\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"_implementation\",\"type\":\"address\"}],\"name\":\"getDeploymentAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenDestinations\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_sigHash\",\"type\":\"bytes4\"}],\"name\":\"isAuthFunctionCall\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"isTokenDestination\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_dst\",\"type\":\"address\"}],\"name\":\"removeTokenDestination\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_target\",\"type\":\"address\"}],\"name\":\"setAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string[]\",\"name\":\"_signatures\",\"type\":\"string[]\"},{\"internalType\":\"address[]\",\"name\":\"_targets\",\"type\":\"address[]\"}],\"name\":\"setAuthFunctionCallMany\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_masterCopy\",\"type\":\"address\"}],\"name\":\"setMasterCopy\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"_signature\",\"type\":\"string\"}],\"name\":\"unsetAuthFunctionCall\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"constructor\":{\"params\":{\"_graphToken\":\"Token to use for deposits and withdrawals\",\"_masterCopy\":\"Address of the master copy to use to clone proxies\"}},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"params\":{\"_beneficiary\":\"Address of the beneficiary of locked tokens\",\"_endTime\":\"End time of the release schedule\",\"_managedAmount\":\"Amount of tokens to be managed by the lock contract\",\"_owner\":\"Address of the contract owner\",\"_periods\":\"Number of periods between start time and end time\",\"_releaseStartTime\":\"Override time for when the releases start\",\"_revocable\":\"Whether the contract is revocable\",\"_startTime\":\"Start time of the release schedule\"}},\"deposit(uint256)\":{\"details\":\"Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes\",\"params\":{\"_amount\":\"Amount to deposit\"}},\"getAuthFunctionCallTarget(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"Address of the target contract where to send the call\"}},\"getDeploymentAddress(bytes32,address)\":{\"details\":\"Uses address(this) as deployer to compute the address. Only for backwards compatibility.\",\"params\":{\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getDeploymentAddress(bytes32,address,address)\":{\"params\":{\"_deployer\":\"Address of the deployer that creates the contract\",\"_implementation\":\"Address of the proxy target implementation\",\"_salt\":\"Bytes32 salt to use for CREATE2\"},\"returns\":{\"_0\":\"Address of the counterfactual MinimalProxy\"}},\"getTokenDestinations()\":{\"returns\":{\"_0\":\"Array of addresses authorized to pull funds from a token lock\"}},\"isAuthFunctionCall(bytes4)\":{\"params\":{\"_sigHash\":\"Function signature hash\"},\"returns\":{\"_0\":\"True if authorized\"}},\"isTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"},\"returns\":{\"_0\":\"True if authorized\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeTokenDestination(address)\":{\"params\":{\"_dst\":\"Destination address\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"setAuthFunctionCall(string,address)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\",\"_target\":\"Address of the destination contract to call\"}},\"setAuthFunctionCallMany(string[],address[])\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signatures\":\"Function signatures\",\"_targets\":\"Address of the destination contract to call\"}},\"setMasterCopy(address)\":{\"params\":{\"_masterCopy\":\"Address of contract bytecode to factory clone\"}},\"token()\":{\"returns\":{\"_0\":\"Token used for transfers and approvals\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"unsetAuthFunctionCall(string)\":{\"details\":\"Input expected is the function signature as 'transfer(address,uint256)'\",\"params\":{\"_signature\":\"Function signature\"}},\"withdraw(uint256)\":{\"details\":\"Escape hatch in case of mistakes or to recover remaining funds\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockManager\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"addTokenDestination(address)\":{\"notice\":\"Adds an address that can be allowed by a token lock to pull funds\"},\"constructor\":{\"notice\":\"Constructor.\"},\"createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)\":{\"notice\":\"Creates and fund a new token lock wallet using a minimum proxy\"},\"deposit(uint256)\":{\"notice\":\"Deposits tokens into the contract\"},\"getAuthFunctionCallTarget(bytes4)\":{\"notice\":\"Gets the target contract to call for a particular function signature\"},\"getDeploymentAddress(bytes32,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getDeploymentAddress(bytes32,address,address)\":{\"notice\":\"Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\"},\"getTokenDestinations()\":{\"notice\":\"Returns an array of authorized destination addresses\"},\"isAuthFunctionCall(bytes4)\":{\"notice\":\"Returns true if the function call is authorized\"},\"isTokenDestination(address)\":{\"notice\":\"Returns True if the address is authorized to be a destination of tokens\"},\"removeTokenDestination(address)\":{\"notice\":\"Removes an address that can be allowed by a token lock to pull funds\"},\"setAuthFunctionCall(string,address)\":{\"notice\":\"Sets an authorized function call to target\"},\"setAuthFunctionCallMany(string[],address[])\":{\"notice\":\"Sets an authorized function call to target in bulk\"},\"setMasterCopy(address)\":{\"notice\":\"Sets the masterCopy bytecode to use to create clones of TokenLock contracts\"},\"token()\":{\"notice\":\"Gets the GRT token address\"},\"unsetAuthFunctionCall(string)\":{\"notice\":\"Unsets an authorized function call to target\"},\"withdraw(uint256)\":{\"notice\":\"Withdraws tokens from the contract\"}},\"notice\":\"This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockManager.sol\":\"GraphTokenLockManager\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"../utils/Context.sol\\\";\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * By default, the owner account will be the one that deploys the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\nabstract contract Ownable is Context {\\n address private _owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n constructor () internal {\\n address msgSender = _msgSender();\\n _owner = msgSender;\\n emit OwnershipTransferred(address(0), msgSender);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view virtual returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(owner() == _msgSender(), \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() public virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) public virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x15e2d5bd4c28a88548074c54d220e8086f638a71ed07e6b3ba5a70066fcf458d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Context.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/*\\n * @dev Provides information about the current execution context, including the\\n * sender of the transaction and its data. While these are generally available\\n * via msg.sender and msg.data, they should not be accessed in such a direct\\n * manner, since when dealing with GSN meta-transactions the account sending and\\n * paying for execution may not be the actual sender (as far as an application\\n * is concerned).\\n *\\n * This contract is only required for intermediate, library-like contracts.\\n */\\nabstract contract Context {\\n function _msgSender() internal view virtual returns (address payable) {\\n return msg.sender;\\n }\\n\\n function _msgData() internal view virtual returns (bytes memory) {\\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\\n return msg.data;\\n }\\n}\\n\",\"keccak256\":\"0x8d3cb350f04ff49cfb10aef08d87f19dcbaecc8027b0bed12f3275cd12f38cf0\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Create2.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\\n * `CREATE2` can be used to compute in advance the address where a smart\\n * contract will be deployed, which allows for interesting new mechanisms known\\n * as 'counterfactual interactions'.\\n *\\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\\n * information.\\n */\\nlibrary Create2 {\\n /**\\n * @dev Deploys a contract using `CREATE2`. The address where the contract\\n * will be deployed can be known in advance via {computeAddress}.\\n *\\n * The bytecode for a contract can be obtained from Solidity with\\n * `type(contractName).creationCode`.\\n *\\n * Requirements:\\n *\\n * - `bytecode` must not be empty.\\n * - `salt` must have not been used for `bytecode` already.\\n * - the factory must have a balance of at least `amount`.\\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\\n */\\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\\n address addr;\\n require(address(this).balance >= amount, \\\"Create2: insufficient balance\\\");\\n require(bytecode.length != 0, \\\"Create2: bytecode length is zero\\\");\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\\n }\\n require(addr != address(0), \\\"Create2: Failed on deploy\\\");\\n return addr;\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\\n * `bytecodeHash` or `salt` will result in a new destination address.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\\n return computeAddress(salt, bytecodeHash, address(this));\\n }\\n\\n /**\\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\\n */\\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\\n bytes32 _data = keccak256(\\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\\n );\\n return address(uint160(uint256(_data)));\\n }\\n}\\n\",\"keccak256\":\"0x0a0b021149946014fe1cd04af11e7a937a29986c47e8b1b718c2d50d729472db\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping (bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) { // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\\n\\n bytes32 lastvalue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastvalue;\\n // Update the index for the moved value\\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n require(set._values.length > index, \\\"EnumerableSet: index out of bounds\\\");\\n return set._values[index];\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n}\\n\",\"keccak256\":\"0x1562cd9922fbf739edfb979f506809e2743789cbde3177515542161c3d04b164\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/EnumerableSet.sol\\\";\\nimport { Ownable } from \\\"@openzeppelin/contracts/access/Ownable.sol\\\";\\n\\nimport \\\"./MinimalProxyFactory.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\nimport { GraphTokenLockWallet } from \\\"./GraphTokenLockWallet.sol\\\";\\n\\n/**\\n * @title GraphTokenLockManager\\n * @notice This contract manages a list of authorized function calls and targets that can be called\\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\\n *\\n * This contract receives funds to make the process of creating TokenLockWallet contracts\\n * easier by distributing them the initial tokens to be managed.\\n *\\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\\n * will manipulate users funds.\\n */\\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\\n using SafeERC20 for IERC20;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n // -- State --\\n\\n mapping(bytes4 => address) public authFnCalls;\\n EnumerableSet.AddressSet private _tokenDestinations;\\n\\n address public masterCopy;\\n IERC20 internal _token;\\n\\n // -- Events --\\n\\n event MasterCopyUpdated(address indexed masterCopy);\\n event TokenLockCreated(\\n address indexed contractAddress,\\n bytes32 indexed initHash,\\n address indexed beneficiary,\\n address token,\\n uint256 managedAmount,\\n uint256 startTime,\\n uint256 endTime,\\n uint256 periods,\\n uint256 releaseStartTime,\\n uint256 vestingCliffTime,\\n IGraphTokenLock.Revocability revocable\\n );\\n\\n event TokensDeposited(address indexed sender, uint256 amount);\\n event TokensWithdrawn(address indexed sender, uint256 amount);\\n\\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\\n event TokenDestinationAllowed(address indexed dst, bool allowed);\\n\\n /**\\n * Constructor.\\n * @param _graphToken Token to use for deposits and withdrawals\\n * @param _masterCopy Address of the master copy to use to clone proxies\\n */\\n constructor(IERC20 _graphToken, address _masterCopy) {\\n require(address(_graphToken) != address(0), \\\"Token cannot be zero\\\");\\n _token = _graphToken;\\n setMasterCopy(_masterCopy);\\n }\\n\\n // -- Factory --\\n\\n /**\\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\\n * @param _masterCopy Address of contract bytecode to factory clone\\n */\\n function setMasterCopy(address _masterCopy) public override onlyOwner {\\n require(_masterCopy != address(0), \\\"MasterCopy cannot be zero\\\");\\n masterCopy = _masterCopy;\\n emit MasterCopyUpdated(_masterCopy);\\n }\\n\\n /**\\n * @notice Creates and fund a new token lock wallet using a minimum proxy\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _revocable Whether the contract is revocable\\n */\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external override onlyOwner {\\n require(_token.balanceOf(address(this)) >= _managedAmount, \\\"Not enough tokens to create lock\\\");\\n\\n // Create contract using a minimal proxy and call initializer\\n bytes memory initializer = abi.encodeWithSelector(\\n GraphTokenLockWallet.initialize.selector,\\n address(this),\\n _owner,\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\\n\\n // Send managed amount to the created contract\\n _token.safeTransfer(contractAddress, _managedAmount);\\n\\n emit TokenLockCreated(\\n contractAddress,\\n keccak256(initializer),\\n _beneficiary,\\n address(_token),\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n }\\n\\n // -- Funds Management --\\n\\n /**\\n * @notice Gets the GRT token address\\n * @return Token used for transfers and approvals\\n */\\n function token() external view override returns (IERC20) {\\n return _token;\\n }\\n\\n /**\\n * @notice Deposits tokens into the contract\\n * @dev Even if the ERC20 token can be transferred directly to the contract\\n * this function provide a safe interface to do the transfer and avoid mistakes\\n * @param _amount Amount to deposit\\n */\\n function deposit(uint256 _amount) external override {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransferFrom(msg.sender, address(this), _amount);\\n emit TokensDeposited(msg.sender, _amount);\\n }\\n\\n /**\\n * @notice Withdraws tokens from the contract\\n * @dev Escape hatch in case of mistakes or to recover remaining funds\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdraw(uint256 _amount) external override onlyOwner {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n _token.safeTransfer(msg.sender, _amount);\\n emit TokensWithdrawn(msg.sender, _amount);\\n }\\n\\n // -- Token Destinations --\\n\\n /**\\n * @notice Adds an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function addTokenDestination(address _dst) external override onlyOwner {\\n require(_dst != address(0), \\\"Destination cannot be zero\\\");\\n require(_tokenDestinations.add(_dst), \\\"Destination already added\\\");\\n emit TokenDestinationAllowed(_dst, true);\\n }\\n\\n /**\\n * @notice Removes an address that can be allowed by a token lock to pull funds\\n * @param _dst Destination address\\n */\\n function removeTokenDestination(address _dst) external override onlyOwner {\\n require(_tokenDestinations.remove(_dst), \\\"Destination already removed\\\");\\n emit TokenDestinationAllowed(_dst, false);\\n }\\n\\n /**\\n * @notice Returns True if the address is authorized to be a destination of tokens\\n * @param _dst Destination address\\n * @return True if authorized\\n */\\n function isTokenDestination(address _dst) external view override returns (bool) {\\n return _tokenDestinations.contains(_dst);\\n }\\n\\n /**\\n * @notice Returns an array of authorized destination addresses\\n * @return Array of addresses authorized to pull funds from a token lock\\n */\\n function getTokenDestinations() external view override returns (address[] memory) {\\n address[] memory dstList = new address[](_tokenDestinations.length());\\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\\n dstList[i] = _tokenDestinations.at(i);\\n }\\n return dstList;\\n }\\n\\n // -- Function Call Authorization --\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\\n _setAuthFunctionCall(_signature, _target);\\n }\\n\\n /**\\n * @notice Unsets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signature Function signature\\n */\\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = address(0);\\n\\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target in bulk\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @param _signatures Function signatures\\n * @param _targets Address of the destination contract to call\\n */\\n function setAuthFunctionCallMany(\\n string[] calldata _signatures,\\n address[] calldata _targets\\n ) external override onlyOwner {\\n require(_signatures.length == _targets.length, \\\"Array length mismatch\\\");\\n\\n for (uint256 i = 0; i < _signatures.length; i++) {\\n _setAuthFunctionCall(_signatures[i], _targets[i]);\\n }\\n }\\n\\n /**\\n * @notice Sets an authorized function call to target\\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\\n * @param _signature Function signature\\n * @param _target Address of the destination contract to call\\n */\\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\\n require(_target != address(this), \\\"Target must be other contract\\\");\\n require(Address.isContract(_target), \\\"Target must be a contract\\\");\\n\\n bytes4 sigHash = _toFunctionSigHash(_signature);\\n authFnCalls[sigHash] = _target;\\n\\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\\n }\\n\\n /**\\n * @notice Gets the target contract to call for a particular function signature\\n * @param _sigHash Function signature hash\\n * @return Address of the target contract where to send the call\\n */\\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\\n return authFnCalls[_sigHash];\\n }\\n\\n /**\\n * @notice Returns true if the function call is authorized\\n * @param _sigHash Function signature hash\\n * @return True if authorized\\n */\\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\\n return getAuthFunctionCallTarget(_sigHash) != address(0);\\n }\\n\\n /**\\n * @dev Converts a function signature string to 4-bytes hash\\n * @param _signature Function signature string\\n * @return Function signature hash\\n */\\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\\n return _convertToBytes4(abi.encodeWithSignature(_signature));\\n }\\n\\n /**\\n * @dev Converts function signature bytes to function signature hash (bytes4)\\n * @param _signature Function signature\\n * @return Function signature in bytes4\\n */\\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\\n require(_signature.length == 4, \\\"Invalid method signature\\\");\\n bytes4 sigHash;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sigHash := mload(add(_signature, 32))\\n }\\n return sigHash;\\n }\\n}\\n\",\"keccak256\":\"0x2bb51cc1a18bd88113fd6947067ad2fff33048c8904cb54adfda8e2ab86752f2\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/MinimalProxyFactory.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport { Create2 } from \\\"@openzeppelin/contracts/utils/Create2.sol\\\";\\n\\n/**\\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\\n * Based on https://eips.ethereum.org/EIPS/eip-1167\\n */\\ncontract MinimalProxyFactory {\\n /// @dev Emitted when a new proxy is created\\n event ProxyCreated(address indexed proxy);\\n\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @dev Uses address(this) as deployer to compute the address. Only for backwards compatibility.\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation\\n ) public view returns (address) {\\n return getDeploymentAddress(_salt, _implementation, address(this));\\n }\\n\\n /**\\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _deployer Address of the deployer that creates the contract\\n * @return Address of the counterfactual MinimalProxy\\n */\\n function getDeploymentAddress(\\n bytes32 _salt,\\n address _implementation,\\n address _deployer\\n ) public pure returns (address) {\\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\\n }\\n\\n /**\\n * @dev Deploys a MinimalProxy with CREATE2\\n * @param _salt Bytes32 salt to use for CREATE2\\n * @param _implementation Address of the proxy target implementation\\n * @param _data Bytes with the initializer call\\n * @return Address of the deployed MinimalProxy\\n */\\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\\n\\n emit ProxyCreated(proxyAddress);\\n\\n // Call function with data\\n if (_data.length > 0) {\\n Address.functionCall(proxyAddress, _data);\\n }\\n\\n return proxyAddress;\\n }\\n\\n /**\\n * @dev Gets the MinimalProxy bytecode\\n * @param _implementation Address of the proxy target implementation\\n * @return MinimalProxy bytecode\\n */\\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\\n bytes10 creation = 0x3d602d80600a3d3981f3;\\n bytes10 prefix = 0x363d3d373d3d3d363d73;\\n bytes20 targetBytes = bytes20(_implementation);\\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\\n }\\n}\\n\",\"keccak256\":\"0xc0ad119f676fe82b234fd5c830d9bc443e9038c0cfe5dc4de3a3bf621d3f69df\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162003d1b38038062003d1b83398181016040528101906200003791906200039c565b600062000049620001b460201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156200015a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200015190620004e7565b60405180910390fd5b81600560006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550620001ac81620001bc60201b60201c565b505062000596565b600033905090565b620001cc620001b460201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16620001f26200034560201b60201c565b73ffffffffffffffffffffffffffffffffffffffff16146200024b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200024290620004c5565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415620002be576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b590620004a3565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6000815190506200037f8162000562565b92915050565b60008151905062000396816200057c565b92915050565b60008060408385031215620003b057600080fd5b6000620003c08582860162000385565b9250506020620003d3858286016200036e565b9150509250929050565b6000620003ec60198362000509565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b60006200042e60208362000509565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b60006200047060148362000509565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006020820190508181036000830152620004be81620003dd565b9050919050565b60006020820190508181036000830152620004e0816200041f565b9050919050565b60006020820190508181036000830152620005028162000461565b9050919050565b600082825260208201905092915050565b6000620005278262000542565b9050919050565b60006200053b826200051a565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6200056d816200051a565b81146200057957600080fd5b50565b62000587816200052e565b81146200059357600080fd5b50565b61377580620005a66000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c80638da5cb5b116100b8578063bdb62fbe1161007c578063bdb62fbe14610324578063c1ab13db14610354578063cf497e6c14610370578063f1d24c451461038c578063f2fde38b146103bc578063fc0c546a146103d857610137565b80638da5cb5b146102925780639c05fc60146102b0578063a3457466146102cc578063a619486e146102ea578063b6b55f251461030857610137565b80635975e00c116100ff5780635975e00c146101f057806368d30c2e1461020c5780636e03b8dc14610228578063715018a61461025857806379ee1bdf1461026257610137565b806303990a6c1461013c5780630602ba2b146101585780632e1a7d4d1461018857806343fb93d9146101a4578063463013a2146101d4575b600080fd5b610156600480360381019061015191906125c6565b6103f6565b005b610172600480360381019061016d919061259d565b61059e565b60405161017f91906130b5565b60405180910390f35b6101a2600480360381019061019d9190612663565b6105df565b005b6101be60048036038101906101b9919061254e565b61073c565b6040516101cb9190612eef565b60405180910390f35b6101ee60048036038101906101e9919061260b565b610761565b005b61020a60048036038101906102059190612385565b6107ed565b005b610226600480360381019061022191906123ae565b61097e565b005b610242600480360381019061023d919061259d565b610cc6565b60405161024f9190612eef565b60405180910390f35b610260610cf9565b005b61027c60048036038101906102779190612385565b610e33565b60405161028991906130b5565b60405180910390f35b61029a610e50565b6040516102a79190612eef565b60405180910390f35b6102ca60048036038101906102c59190612474565b610e79565b005b6102d4610fa6565b6040516102e19190613093565b60405180910390f35b6102f261107e565b6040516102ff9190612eef565b60405180910390f35b610322600480360381019061031d9190612663565b6110a4565b005b61033e60048036038101906103399190612512565b611187565b60405161034b9190612eef565b60405180910390f35b61036e60048036038101906103699190612385565b61119c565b005b61038a60048036038101906103859190612385565b6112bd565b005b6103a660048036038101906103a1919061259d565b611430565b6040516103b39190612eef565b60405180910390f35b6103d660048036038101906103d19190612385565b6114ab565b005b6103e0611654565b6040516103ed91906130d0565b60405180910390f35b6103fe61167e565b73ffffffffffffffffffffffffffffffffffffffff1661041c610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610472576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610469906132b1565b60405180910390fd5b600061047e8383611686565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c986866040516105919291906130eb565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff166105c083611430565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105e761167e565b73ffffffffffffffffffffffffffffffffffffffff16610605610e50565b73ffffffffffffffffffffffffffffffffffffffff161461065b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610652906132b1565b60405180910390fd5b6000811161069e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161069590613291565b60405180910390fd5b6106eb3382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117149092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516107319190613391565b60405180910390a250565b60006107588461074b8561179a565b8051906020012084611810565b90509392505050565b61076961167e565b73ffffffffffffffffffffffffffffffffffffffff16610787610e50565b73ffffffffffffffffffffffffffffffffffffffff16146107dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107d4906132b1565b60405180910390fd5b6107e8838383611854565b505050565b6107f561167e565b73ffffffffffffffffffffffffffffffffffffffff16610813610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610869576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610860906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156108d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d090613191565b60405180910390fd5b6108ed816002611a3690919063ffffffff16565b61092c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610923906132f1565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a79600160405161097391906130b5565b60405180910390a250565b61098661167e565b73ffffffffffffffffffffffffffffffffffffffff166109a4610e50565b73ffffffffffffffffffffffffffffffffffffffff16146109fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f1906132b1565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a569190612eef565b60206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa6919061268c565b1015610ae7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ade906131d1565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610b389b9a99989796959493929190612f0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610bcd8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a66565b9050610c1c818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117149092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610cb1989796959493929190613015565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d0161167e565b73ffffffffffffffffffffffffffffffffffffffff16610d1f610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610d75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6c906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e49826002611ae290919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e8161167e565b73ffffffffffffffffffffffffffffffffffffffff16610e9f610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906132b1565b60405180910390fd5b818190508484905014610f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3490613171565b60405180910390fd5b60005b84849050811015610f9f57610f92858583818110610f5a57fe5b9050602002810190610f6c91906133ac565b858585818110610f7857fe5b9050602002016020810190610f8d9190612385565b611854565b8080600101915050610f40565b5050505050565b606080610fb36002611b12565b67ffffffffffffffff81118015610fc957600080fd5b50604051908082528060200260200182016040528015610ff85781602001602082028036833780820191505090505b50905060005b6110086002611b12565b81101561107657611023816002611b2790919063ffffffff16565b82828151811061102f57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610ffe565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116110e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110de90613291565b60405180910390fd5b611136333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611b41909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e8260405161117c9190613391565b60405180910390a250565b600061119483833061073c565b905092915050565b6111a461167e565b73ffffffffffffffffffffffffffffffffffffffff166111c2610e50565b73ffffffffffffffffffffffffffffffffffffffff1614611218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120f906132b1565b60405180910390fd5b61122c816002611bca90919063ffffffff16565b61126b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126290613211565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516112b291906130b5565b60405180910390a250565b6112c561167e565b73ffffffffffffffffffffffffffffffffffffffff166112e3610e50565b73ffffffffffffffffffffffffffffffffffffffff1614611339576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611330906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156113a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a090613231565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6114b361167e565b73ffffffffffffffffffffffffffffffffffffffff166114d1610e50565b73ffffffffffffffffffffffffffffffffffffffff1614611527576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151e906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611597576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158e906131b1565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b600061170c838360405160240160405160208183030381529060405291906040516116b2929190612ed6565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bfa565b905092915050565b6117958363a9059cbb60e01b8484604051602401611733929190612fec565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c52565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b9050838383836040516020016117f69493929190612e23565b604051602081830303815290604052945050505050919050565b60008060ff60f81b83868660405160200161182e9493929190612e71565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ba90613251565b60405180910390fd5b6118cc81611d19565b61190b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190290613371565b60405180910390fd5b60006119178484611686565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611a289291906130eb565b60405180910390a450505050565b6000611a5e836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611d2c565b905092915050565b600080611a7d600086611a788761179a565b611d9c565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611ad757611ad58184611ead565b505b809150509392505050565b6000611b0a836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ef7565b905092915050565b6000611b2082600001611f1a565b9050919050565b6000611b368360000183611f2b565b60001c905092915050565b611bc4846323b872dd60e01b858585604051602401611b6293929190612fb5565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c52565b50505050565b6000611bf2836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f98565b905092915050565b60006004825114611c40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c37906132d1565b60405180910390fd5b60006020830151905080915050919050565b6060611cb4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120809092919063ffffffff16565b9050600081511115611d145780806020019051810190611cd491906124e9565b611d13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0a90613331565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611d388383611ef7565b611d91578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d96565b600090505b92915050565b60008084471015611de2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd990613351565b60405180910390fd5b600083511415611e27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1e90613151565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611ea2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9990613271565b60405180910390fd5b809150509392505050565b6060611eef83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612080565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90613131565b60405180910390fd5b826000018281548110611f8557fe5b9060005260206000200154905092915050565b600080836001016000848152602001908152602001600020549050600081146120745760006001820390506000600186600001805490500390506000866000018281548110611fe357fe5b906000526020600020015490508087600001848154811061200057fe5b906000526020600020018190555060018301876001016000838152602001908152602001600020819055508660000180548061203857fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061207a565b60009150505b92915050565b606061208f8484600085612098565b90509392505050565b6060824710156120dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120d4906131f1565b60405180910390fd5b6120e685611d19565b612125576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161211c90613311565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161214f9190612ebf565b60006040518083038185875af1925050503d806000811461218c576040519150601f19603f3d011682016040523d82523d6000602084013e612191565b606091505b50915091506121a18282866121ad565b92505050949350505050565b606083156121bd5782905061220d565b6000835111156121d05782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612204919061310f565b60405180910390fd5b9392505050565b600081359050612223816136bc565b92915050565b60008083601f84011261223b57600080fd5b8235905067ffffffffffffffff81111561225457600080fd5b60208301915083602082028301111561226c57600080fd5b9250929050565b60008083601f84011261228557600080fd5b8235905067ffffffffffffffff81111561229e57600080fd5b6020830191508360208202830111156122b657600080fd5b9250929050565b6000815190506122cc816136d3565b92915050565b6000813590506122e1816136ea565b92915050565b6000813590506122f681613701565b92915050565b60008135905061230b81613718565b92915050565b60008083601f84011261232357600080fd5b8235905067ffffffffffffffff81111561233c57600080fd5b60208301915083600182028301111561235457600080fd5b9250929050565b60008135905061236a81613728565b92915050565b60008151905061237f81613728565b92915050565b60006020828403121561239757600080fd5b60006123a584828501612214565b91505092915050565b60008060008060008060008060006101208a8c0312156123cd57600080fd5b60006123db8c828d01612214565b99505060206123ec8c828d01612214565b98505060406123fd8c828d0161235b565b975050606061240e8c828d0161235b565b965050608061241f8c828d0161235b565b95505060a06124308c828d0161235b565b94505060c06124418c828d0161235b565b93505060e06124528c828d0161235b565b9250506101006124648c828d016122fc565b9150509295985092959850929598565b6000806000806040858703121561248a57600080fd5b600085013567ffffffffffffffff8111156124a457600080fd5b6124b087828801612273565b9450945050602085013567ffffffffffffffff8111156124cf57600080fd5b6124db87828801612229565b925092505092959194509250565b6000602082840312156124fb57600080fd5b6000612509848285016122bd565b91505092915050565b6000806040838503121561252557600080fd5b6000612533858286016122d2565b925050602061254485828601612214565b9150509250929050565b60008060006060848603121561256357600080fd5b6000612571868287016122d2565b935050602061258286828701612214565b925050604061259386828701612214565b9150509250925092565b6000602082840312156125af57600080fd5b60006125bd848285016122e7565b91505092915050565b600080602083850312156125d957600080fd5b600083013567ffffffffffffffff8111156125f357600080fd5b6125ff85828601612311565b92509250509250929050565b60008060006040848603121561262057600080fd5b600084013567ffffffffffffffff81111561263a57600080fd5b61264686828701612311565b9350935050602061265986828701612214565b9150509250925092565b60006020828403121561267557600080fd5b60006126838482850161235b565b91505092915050565b60006020828403121561269e57600080fd5b60006126ac84828501612370565b91505092915050565b60006126c183836126cd565b60208301905092915050565b6126d681613479565b82525050565b6126e581613479565b82525050565b6126fc6126f782613479565b613632565b82525050565b600061270d82613413565b6127178185613441565b935061272283613403565b8060005b8381101561275357815161273a88826126b5565b975061274583613434565b925050600181019050612726565b5085935050505092915050565b6127698161348b565b82525050565b61278061277b826134c3565b61364e565b82525050565b612797612792826134ef565b613658565b82525050565b6127ae6127a982613497565b613644565b82525050565b6127c56127c08261351b565b613662565b82525050565b6127dc6127d782613547565b61366c565b82525050565b60006127ed8261341e565b6127f78185613452565b93506128078185602086016135ff565b80840191505092915050565b61281c816135ba565b82525050565b61282b816135de565b82525050565b600061283d838561345d565b935061284a8385846135f0565b6128538361368a565b840190509392505050565b600061286a838561346e565b93506128778385846135f0565b82840190509392505050565b600061288e82613429565b612898818561345d565b93506128a88185602086016135ff565b6128b18161368a565b840191505092915050565b60006128c960228361345d565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061292f60208361345d565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b600061296f60158361345d565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b60006129af601a8361345d565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129ef60268361345d565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a5560208361345d565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a9560268361345d565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612afb601b8361345d565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612b3b60198361345d565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612b7b601d8361345d565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612bbb60198361345d565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612bfb60158361345d565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612c3b60208361345d565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612c7b60188361345d565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612cbb60198361345d565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612cfb601d8361345d565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612d3b602a8361345d565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612da1601d8361345d565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612de160198361345d565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612e1d816135b0565b82525050565b6000612e2f828761276f565b600a82019150612e3f828661276f565b600a82019150612e4f82856127b4565b601482019150612e5f8284612786565b600f8201915081905095945050505050565b6000612e7d828761279d565b600182019150612e8d82866126eb565b601482019150612e9d82856127cb565b602082019150612ead82846127cb565b60208201915081905095945050505050565b6000612ecb82846127e2565b915081905092915050565b6000612ee382848661285e565b91508190509392505050565b6000602082019050612f0460008301846126dc565b92915050565b600061016082019050612f20600083018e6126dc565b612f2d602083018d6126dc565b612f3a604083018c6126dc565b612f47606083018b6126dc565b612f54608083018a612e14565b612f6160a0830189612e14565b612f6e60c0830188612e14565b612f7b60e0830187612e14565b612f89610100830186612e14565b612f97610120830185612e14565b612fa5610140830184612822565b9c9b505050505050505050505050565b6000606082019050612fca60008301866126dc565b612fd760208301856126dc565b612fe46040830184612e14565b949350505050565b600060408201905061300160008301856126dc565b61300e6020830184612e14565b9392505050565b60006101008201905061302b600083018b6126dc565b613038602083018a612e14565b6130456040830189612e14565b6130526060830188612e14565b61305f6080830187612e14565b61306c60a0830186612e14565b61307960c0830185612e14565b61308660e0830184612822565b9998505050505050505050565b600060208201905081810360008301526130ad8184612702565b905092915050565b60006020820190506130ca6000830184612760565b92915050565b60006020820190506130e56000830184612813565b92915050565b60006020820190508181036000830152613106818486612831565b90509392505050565b600060208201905081810360008301526131298184612883565b905092915050565b6000602082019050818103600083015261314a816128bc565b9050919050565b6000602082019050818103600083015261316a81612922565b9050919050565b6000602082019050818103600083015261318a81612962565b9050919050565b600060208201905081810360008301526131aa816129a2565b9050919050565b600060208201905081810360008301526131ca816129e2565b9050919050565b600060208201905081810360008301526131ea81612a48565b9050919050565b6000602082019050818103600083015261320a81612a88565b9050919050565b6000602082019050818103600083015261322a81612aee565b9050919050565b6000602082019050818103600083015261324a81612b2e565b9050919050565b6000602082019050818103600083015261326a81612b6e565b9050919050565b6000602082019050818103600083015261328a81612bae565b9050919050565b600060208201905081810360008301526132aa81612bee565b9050919050565b600060208201905081810360008301526132ca81612c2e565b9050919050565b600060208201905081810360008301526132ea81612c6e565b9050919050565b6000602082019050818103600083015261330a81612cae565b9050919050565b6000602082019050818103600083015261332a81612cee565b9050919050565b6000602082019050818103600083015261334a81612d2e565b9050919050565b6000602082019050818103600083015261336a81612d94565b9050919050565b6000602082019050818103600083015261338a81612dd4565b9050919050565b60006020820190506133a66000830184612e14565b92915050565b600080833560016020038436030381126133c557600080fd5b80840192508235915067ffffffffffffffff8211156133e357600080fd5b6020830192506001820236038313156133fb57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061348482613590565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061358b826136a8565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006135c5826135cc565b9050919050565b60006135d782613590565b9050919050565b60006135e98261357d565b9050919050565b82818337600083830152505050565b60005b8381101561361d578082015181840152602081019050613602565b8381111561362c576000848401525b50505050565b600061363d82613676565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006136818261369b565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b600381106136b9576136b8613688565b5b50565b6136c581613479565b81146136d057600080fd5b50565b6136dc8161348b565b81146136e757600080fd5b50565b6136f381613547565b81146136fe57600080fd5b50565b61370a81613551565b811461371557600080fd5b50565b6003811061372557600080fd5b50565b613731816135b0565b811461373c57600080fd5b5056fea2646970667358221220581ad1bb71f757e3f7e84aec2c69a43e2d33acbd90669e872c9dd5a180a59a6764736f6c63430007030033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101375760003560e01c80638da5cb5b116100b8578063bdb62fbe1161007c578063bdb62fbe14610324578063c1ab13db14610354578063cf497e6c14610370578063f1d24c451461038c578063f2fde38b146103bc578063fc0c546a146103d857610137565b80638da5cb5b146102925780639c05fc60146102b0578063a3457466146102cc578063a619486e146102ea578063b6b55f251461030857610137565b80635975e00c116100ff5780635975e00c146101f057806368d30c2e1461020c5780636e03b8dc14610228578063715018a61461025857806379ee1bdf1461026257610137565b806303990a6c1461013c5780630602ba2b146101585780632e1a7d4d1461018857806343fb93d9146101a4578063463013a2146101d4575b600080fd5b610156600480360381019061015191906125c6565b6103f6565b005b610172600480360381019061016d919061259d565b61059e565b60405161017f91906130b5565b60405180910390f35b6101a2600480360381019061019d9190612663565b6105df565b005b6101be60048036038101906101b9919061254e565b61073c565b6040516101cb9190612eef565b60405180910390f35b6101ee60048036038101906101e9919061260b565b610761565b005b61020a60048036038101906102059190612385565b6107ed565b005b610226600480360381019061022191906123ae565b61097e565b005b610242600480360381019061023d919061259d565b610cc6565b60405161024f9190612eef565b60405180910390f35b610260610cf9565b005b61027c60048036038101906102779190612385565b610e33565b60405161028991906130b5565b60405180910390f35b61029a610e50565b6040516102a79190612eef565b60405180910390f35b6102ca60048036038101906102c59190612474565b610e79565b005b6102d4610fa6565b6040516102e19190613093565b60405180910390f35b6102f261107e565b6040516102ff9190612eef565b60405180910390f35b610322600480360381019061031d9190612663565b6110a4565b005b61033e60048036038101906103399190612512565b611187565b60405161034b9190612eef565b60405180910390f35b61036e60048036038101906103699190612385565b61119c565b005b61038a60048036038101906103859190612385565b6112bd565b005b6103a660048036038101906103a1919061259d565b611430565b6040516103b39190612eef565b60405180910390f35b6103d660048036038101906103d19190612385565b6114ab565b005b6103e0611654565b6040516103ed91906130d0565b60405180910390f35b6103fe61167e565b73ffffffffffffffffffffffffffffffffffffffff1661041c610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610472576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610469906132b1565b60405180910390fd5b600061047e8383611686565b9050600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550600073ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c986866040516105919291906130eb565b60405180910390a4505050565b60008073ffffffffffffffffffffffffffffffffffffffff166105c083611430565b73ffffffffffffffffffffffffffffffffffffffff1614159050919050565b6105e761167e565b73ffffffffffffffffffffffffffffffffffffffff16610605610e50565b73ffffffffffffffffffffffffffffffffffffffff161461065b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610652906132b1565b60405180910390fd5b6000811161069e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161069590613291565b60405180910390fd5b6106eb3382600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117149092919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b826040516107319190613391565b60405180910390a250565b60006107588461074b8561179a565b8051906020012084611810565b90509392505050565b61076961167e565b73ffffffffffffffffffffffffffffffffffffffff16610787610e50565b73ffffffffffffffffffffffffffffffffffffffff16146107dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107d4906132b1565b60405180910390fd5b6107e8838383611854565b505050565b6107f561167e565b73ffffffffffffffffffffffffffffffffffffffff16610813610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610869576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610860906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156108d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108d090613191565b60405180910390fd5b6108ed816002611a3690919063ffffffff16565b61092c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610923906132f1565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a79600160405161097391906130b5565b60405180910390a250565b61098661167e565b73ffffffffffffffffffffffffffffffffffffffff166109a4610e50565b73ffffffffffffffffffffffffffffffffffffffff16146109fa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109f1906132b1565b60405180910390fd5b86600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610a569190612eef565b60206040518083038186803b158015610a6e57600080fd5b505afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa6919061268c565b1015610ae7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ade906131d1565b60405180910390fd5b606063bd896dcb60e01b308b8b600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168c8c8c8c8c8c8c604051602401610b389b9a99989796959493929190612f0a565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505090506000610bcd8280519060200120600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684611a66565b9050610c1c818a600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166117149092919063ffffffff16565b8973ffffffffffffffffffffffffffffffffffffffff1682805190602001208273ffffffffffffffffffffffffffffffffffffffff167f3c7ff6acee351ed98200c285a04745858a107e16da2f13c3a81a43073c17d644600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168d8d8d8d8d8d8d604051610cb1989796959493929190613015565b60405180910390a45050505050505050505050565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b610d0161167e565b73ffffffffffffffffffffffffffffffffffffffff16610d1f610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610d75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d6c906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6000610e49826002611ae290919063ffffffff16565b9050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610e8161167e565b73ffffffffffffffffffffffffffffffffffffffff16610e9f610e50565b73ffffffffffffffffffffffffffffffffffffffff1614610ef5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610eec906132b1565b60405180910390fd5b818190508484905014610f3d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f3490613171565b60405180910390fd5b60005b84849050811015610f9f57610f92858583818110610f5a57fe5b9050602002810190610f6c91906133ac565b858585818110610f7857fe5b9050602002016020810190610f8d9190612385565b611854565b8080600101915050610f40565b5050505050565b606080610fb36002611b12565b67ffffffffffffffff81118015610fc957600080fd5b50604051908082528060200260200182016040528015610ff85781602001602082028036833780820191505090505b50905060005b6110086002611b12565b81101561107657611023816002611b2790919063ffffffff16565b82828151811061102f57fe5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250508080600101915050610ffe565b508091505090565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600081116110e7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110de90613291565b60405180910390fd5b611136333083600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16611b41909392919063ffffffff16565b3373ffffffffffffffffffffffffffffffffffffffff167f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e8260405161117c9190613391565b60405180910390a250565b600061119483833061073c565b905092915050565b6111a461167e565b73ffffffffffffffffffffffffffffffffffffffff166111c2610e50565b73ffffffffffffffffffffffffffffffffffffffff1614611218576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161120f906132b1565b60405180910390fd5b61122c816002611bca90919063ffffffff16565b61126b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161126290613211565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff167f33442b8c13e72dd75a027f08f9bff4eed2dfd26e43cdea857365f5163b359a7960006040516112b291906130b5565b60405180910390a250565b6112c561167e565b73ffffffffffffffffffffffffffffffffffffffff166112e3610e50565b73ffffffffffffffffffffffffffffffffffffffff1614611339576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611330906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156113a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016113a090613231565b60405180910390fd5b80600460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff167f30909084afc859121ffc3a5aef7fe37c540a9a1ef60bd4d8dcdb76376fadf9de60405160405180910390a250565b600060016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b6114b361167e565b73ffffffffffffffffffffffffffffffffffffffff166114d1610e50565b73ffffffffffffffffffffffffffffffffffffffff1614611527576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151e906132b1565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611597576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158e906131b1565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000600560009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600033905090565b600061170c838360405160240160405160208183030381529060405291906040516116b2929190612ed6565b60405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611bfa565b905092915050565b6117958363a9059cbb60e01b8484604051602401611733929190612fec565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c52565b505050565b60606000693d602d80600a3d3981f360b01b9050600069363d3d373d3d3d363d7360b01b905060008460601b905060006e5af43d82803e903d91602b57fd5bf360881b9050838383836040516020016117f69493929190612e23565b604051602081830303815290604052945050505050919050565b60008060ff60f81b83868660405160200161182e9493929190612e71565b6040516020818303038152906040528051906020012090508060001c9150509392505050565b3073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156118c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016118ba90613251565b60405180910390fd5b6118cc81611d19565b61190b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190290613371565b60405180910390fd5b60006119178484611686565b90508160016000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff16817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19163373ffffffffffffffffffffffffffffffffffffffff167f450397a2db0e89eccfe664cc6cdfd274a88bc00d29aaec4d991754a42f19f8c98787604051611a289291906130eb565b60405180910390a450505050565b6000611a5e836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611d2c565b905092915050565b600080611a7d600086611a788761179a565b611d9c565b90508073ffffffffffffffffffffffffffffffffffffffff167efffc2da0b561cae30d9826d37709e9421c4725faebc226cbbb7ef5fc5e734960405160405180910390a2600083511115611ad757611ad58184611ead565b505b809150509392505050565b6000611b0a836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611ef7565b905092915050565b6000611b2082600001611f1a565b9050919050565b6000611b368360000183611f2b565b60001c905092915050565b611bc4846323b872dd60e01b858585604051602401611b6293929190612fb5565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611c52565b50505050565b6000611bf2836000018373ffffffffffffffffffffffffffffffffffffffff1660001b611f98565b905092915050565b60006004825114611c40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c37906132d1565b60405180910390fd5b60006020830151905080915050919050565b6060611cb4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166120809092919063ffffffff16565b9050600081511115611d145780806020019051810190611cd491906124e9565b611d13576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d0a90613331565b60405180910390fd5b5b505050565b600080823b905060008111915050919050565b6000611d388383611ef7565b611d91578260000182908060018154018082558091505060019003906000526020600020016000909190919091505582600001805490508360010160008481526020019081526020016000208190555060019050611d96565b600090505b92915050565b60008084471015611de2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd990613351565b60405180910390fd5b600083511415611e27576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e1e90613151565b60405180910390fd5b8383516020850187f59050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415611ea2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e9990613271565b60405180910390fd5b809150509392505050565b6060611eef83836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612080565b905092915050565b600080836001016000848152602001908152602001600020541415905092915050565b600081600001805490509050919050565b600081836000018054905011611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90613131565b60405180910390fd5b826000018281548110611f8557fe5b9060005260206000200154905092915050565b600080836001016000848152602001908152602001600020549050600081146120745760006001820390506000600186600001805490500390506000866000018281548110611fe357fe5b906000526020600020015490508087600001848154811061200057fe5b906000526020600020018190555060018301876001016000838152602001908152602001600020819055508660000180548061203857fe5b6001900381819060005260206000200160009055905586600101600087815260200190815260200160002060009055600194505050505061207a565b60009150505b92915050565b606061208f8484600085612098565b90509392505050565b6060824710156120dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120d4906131f1565b60405180910390fd5b6120e685611d19565b612125576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161211c90613311565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff16858760405161214f9190612ebf565b60006040518083038185875af1925050503d806000811461218c576040519150601f19603f3d011682016040523d82523d6000602084013e612191565b606091505b50915091506121a18282866121ad565b92505050949350505050565b606083156121bd5782905061220d565b6000835111156121d05782518084602001fd5b816040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612204919061310f565b60405180910390fd5b9392505050565b600081359050612223816136bc565b92915050565b60008083601f84011261223b57600080fd5b8235905067ffffffffffffffff81111561225457600080fd5b60208301915083602082028301111561226c57600080fd5b9250929050565b60008083601f84011261228557600080fd5b8235905067ffffffffffffffff81111561229e57600080fd5b6020830191508360208202830111156122b657600080fd5b9250929050565b6000815190506122cc816136d3565b92915050565b6000813590506122e1816136ea565b92915050565b6000813590506122f681613701565b92915050565b60008135905061230b81613718565b92915050565b60008083601f84011261232357600080fd5b8235905067ffffffffffffffff81111561233c57600080fd5b60208301915083600182028301111561235457600080fd5b9250929050565b60008135905061236a81613728565b92915050565b60008151905061237f81613728565b92915050565b60006020828403121561239757600080fd5b60006123a584828501612214565b91505092915050565b60008060008060008060008060006101208a8c0312156123cd57600080fd5b60006123db8c828d01612214565b99505060206123ec8c828d01612214565b98505060406123fd8c828d0161235b565b975050606061240e8c828d0161235b565b965050608061241f8c828d0161235b565b95505060a06124308c828d0161235b565b94505060c06124418c828d0161235b565b93505060e06124528c828d0161235b565b9250506101006124648c828d016122fc565b9150509295985092959850929598565b6000806000806040858703121561248a57600080fd5b600085013567ffffffffffffffff8111156124a457600080fd5b6124b087828801612273565b9450945050602085013567ffffffffffffffff8111156124cf57600080fd5b6124db87828801612229565b925092505092959194509250565b6000602082840312156124fb57600080fd5b6000612509848285016122bd565b91505092915050565b6000806040838503121561252557600080fd5b6000612533858286016122d2565b925050602061254485828601612214565b9150509250929050565b60008060006060848603121561256357600080fd5b6000612571868287016122d2565b935050602061258286828701612214565b925050604061259386828701612214565b9150509250925092565b6000602082840312156125af57600080fd5b60006125bd848285016122e7565b91505092915050565b600080602083850312156125d957600080fd5b600083013567ffffffffffffffff8111156125f357600080fd5b6125ff85828601612311565b92509250509250929050565b60008060006040848603121561262057600080fd5b600084013567ffffffffffffffff81111561263a57600080fd5b61264686828701612311565b9350935050602061265986828701612214565b9150509250925092565b60006020828403121561267557600080fd5b60006126838482850161235b565b91505092915050565b60006020828403121561269e57600080fd5b60006126ac84828501612370565b91505092915050565b60006126c183836126cd565b60208301905092915050565b6126d681613479565b82525050565b6126e581613479565b82525050565b6126fc6126f782613479565b613632565b82525050565b600061270d82613413565b6127178185613441565b935061272283613403565b8060005b8381101561275357815161273a88826126b5565b975061274583613434565b925050600181019050612726565b5085935050505092915050565b6127698161348b565b82525050565b61278061277b826134c3565b61364e565b82525050565b612797612792826134ef565b613658565b82525050565b6127ae6127a982613497565b613644565b82525050565b6127c56127c08261351b565b613662565b82525050565b6127dc6127d782613547565b61366c565b82525050565b60006127ed8261341e565b6127f78185613452565b93506128078185602086016135ff565b80840191505092915050565b61281c816135ba565b82525050565b61282b816135de565b82525050565b600061283d838561345d565b935061284a8385846135f0565b6128538361368a565b840190509392505050565b600061286a838561346e565b93506128778385846135f0565b82840190509392505050565b600061288e82613429565b612898818561345d565b93506128a88185602086016135ff565b6128b18161368a565b840191505092915050565b60006128c960228361345d565b91507f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e60008301527f64730000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b600061292f60208361345d565b91507f437265617465323a2062797465636f6465206c656e677468206973207a65726f6000830152602082019050919050565b600061296f60158361345d565b91507f4172726179206c656e677468206d69736d6174636800000000000000000000006000830152602082019050919050565b60006129af601a8361345d565b91507f44657374696e6174696f6e2063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b60006129ef60268361345d565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612a5560208361345d565b91507f4e6f7420656e6f75676820746f6b656e7320746f20637265617465206c6f636b6000830152602082019050919050565b6000612a9560268361345d565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612afb601b8361345d565b91507f44657374696e6174696f6e20616c72656164792072656d6f76656400000000006000830152602082019050919050565b6000612b3b60198361345d565b91507f4d6173746572436f70792063616e6e6f74206265207a65726f000000000000006000830152602082019050919050565b6000612b7b601d8361345d565b91507f546172676574206d757374206265206f7468657220636f6e74726163740000006000830152602082019050919050565b6000612bbb60198361345d565b91507f437265617465323a204661696c6564206f6e206465706c6f79000000000000006000830152602082019050919050565b6000612bfb60158361345d565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b6000612c3b60208361345d565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000612c7b60188361345d565b91507f496e76616c6964206d6574686f64207369676e617475726500000000000000006000830152602082019050919050565b6000612cbb60198361345d565b91507f44657374696e6174696f6e20616c7265616479206164646564000000000000006000830152602082019050919050565b6000612cfb601d8361345d565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000612d3b602a8361345d565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000612da1601d8361345d565b91507f437265617465323a20696e73756666696369656e742062616c616e63650000006000830152602082019050919050565b6000612de160198361345d565b91507f546172676574206d757374206265206120636f6e7472616374000000000000006000830152602082019050919050565b612e1d816135b0565b82525050565b6000612e2f828761276f565b600a82019150612e3f828661276f565b600a82019150612e4f82856127b4565b601482019150612e5f8284612786565b600f8201915081905095945050505050565b6000612e7d828761279d565b600182019150612e8d82866126eb565b601482019150612e9d82856127cb565b602082019150612ead82846127cb565b60208201915081905095945050505050565b6000612ecb82846127e2565b915081905092915050565b6000612ee382848661285e565b91508190509392505050565b6000602082019050612f0460008301846126dc565b92915050565b600061016082019050612f20600083018e6126dc565b612f2d602083018d6126dc565b612f3a604083018c6126dc565b612f47606083018b6126dc565b612f54608083018a612e14565b612f6160a0830189612e14565b612f6e60c0830188612e14565b612f7b60e0830187612e14565b612f89610100830186612e14565b612f97610120830185612e14565b612fa5610140830184612822565b9c9b505050505050505050505050565b6000606082019050612fca60008301866126dc565b612fd760208301856126dc565b612fe46040830184612e14565b949350505050565b600060408201905061300160008301856126dc565b61300e6020830184612e14565b9392505050565b60006101008201905061302b600083018b6126dc565b613038602083018a612e14565b6130456040830189612e14565b6130526060830188612e14565b61305f6080830187612e14565b61306c60a0830186612e14565b61307960c0830185612e14565b61308660e0830184612822565b9998505050505050505050565b600060208201905081810360008301526130ad8184612702565b905092915050565b60006020820190506130ca6000830184612760565b92915050565b60006020820190506130e56000830184612813565b92915050565b60006020820190508181036000830152613106818486612831565b90509392505050565b600060208201905081810360008301526131298184612883565b905092915050565b6000602082019050818103600083015261314a816128bc565b9050919050565b6000602082019050818103600083015261316a81612922565b9050919050565b6000602082019050818103600083015261318a81612962565b9050919050565b600060208201905081810360008301526131aa816129a2565b9050919050565b600060208201905081810360008301526131ca816129e2565b9050919050565b600060208201905081810360008301526131ea81612a48565b9050919050565b6000602082019050818103600083015261320a81612a88565b9050919050565b6000602082019050818103600083015261322a81612aee565b9050919050565b6000602082019050818103600083015261324a81612b2e565b9050919050565b6000602082019050818103600083015261326a81612b6e565b9050919050565b6000602082019050818103600083015261328a81612bae565b9050919050565b600060208201905081810360008301526132aa81612bee565b9050919050565b600060208201905081810360008301526132ca81612c2e565b9050919050565b600060208201905081810360008301526132ea81612c6e565b9050919050565b6000602082019050818103600083015261330a81612cae565b9050919050565b6000602082019050818103600083015261332a81612cee565b9050919050565b6000602082019050818103600083015261334a81612d2e565b9050919050565b6000602082019050818103600083015261336a81612d94565b9050919050565b6000602082019050818103600083015261338a81612dd4565b9050919050565b60006020820190506133a66000830184612e14565b92915050565b600080833560016020038436030381126133c557600080fd5b80840192508235915067ffffffffffffffff8211156133e357600080fd5b6020830192506001820236038313156133fb57600080fd5b509250929050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600061348482613590565b9050919050565b60008115159050919050565b60007fff0000000000000000000000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffff0000000000000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffff000000000000000000000000000000000082169050919050565b60007fffffffffffffffffffffffffffffffffffffffff00000000000000000000000082169050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061358b826136a8565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006135c5826135cc565b9050919050565b60006135d782613590565b9050919050565b60006135e98261357d565b9050919050565b82818337600083830152505050565b60005b8381101561361d578082015181840152602081019050613602565b8381111561362c576000848401525b50505050565b600061363d82613676565b9050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b60006136818261369b565b9050919050565bfe5b6000601f19601f8301169050919050565b60008160601b9050919050565b600381106136b9576136b8613688565b5b50565b6136c581613479565b81146136d057600080fd5b50565b6136dc8161348b565b81146136e757600080fd5b50565b6136f381613547565b81146136fe57600080fd5b50565b61370a81613551565b811461371557600080fd5b50565b6003811061372557600080fd5b50565b613731816135b0565b811461373c57600080fd5b5056fea2646970667358221220581ad1bb71f757e3f7e84aec2c69a43e2d33acbd90669e872c9dd5a180a59a6764736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "addTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "constructor": { + "params": { + "_graphToken": "Token to use for deposits and withdrawals", + "_masterCopy": "Address of the master copy to use to clone proxies" + } + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "params": { + "_beneficiary": "Address of the beneficiary of locked tokens", + "_endTime": "End time of the release schedule", + "_managedAmount": "Amount of tokens to be managed by the lock contract", + "_owner": "Address of the contract owner", + "_periods": "Number of periods between start time and end time", + "_releaseStartTime": "Override time for when the releases start", + "_revocable": "Whether the contract is revocable", + "_startTime": "Start time of the release schedule" + } + }, + "deposit(uint256)": { + "details": "Even if the ERC20 token can be transferred directly to the contract this function provide a safe interface to do the transfer and avoid mistakes", + "params": { + "_amount": "Amount to deposit" + } + }, + "getAuthFunctionCallTarget(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "Address of the target contract where to send the call" + } + }, + "getDeploymentAddress(bytes32,address)": { + "details": "Uses address(this) as deployer to compute the address. Only for backwards compatibility.", + "params": { + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getDeploymentAddress(bytes32,address,address)": { + "params": { + "_deployer": "Address of the deployer that creates the contract", + "_implementation": "Address of the proxy target implementation", + "_salt": "Bytes32 salt to use for CREATE2" + }, + "returns": { + "_0": "Address of the counterfactual MinimalProxy" + } + }, + "getTokenDestinations()": { + "returns": { + "_0": "Array of addresses authorized to pull funds from a token lock" + } + }, + "isAuthFunctionCall(bytes4)": { + "params": { + "_sigHash": "Function signature hash" + }, + "returns": { + "_0": "True if authorized" + } + }, + "isTokenDestination(address)": { + "params": { + "_dst": "Destination address" + }, + "returns": { + "_0": "True if authorized" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "removeTokenDestination(address)": { + "params": { + "_dst": "Destination address" + } + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "setAuthFunctionCall(string,address)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature", + "_target": "Address of the destination contract to call" + } + }, + "setAuthFunctionCallMany(string[],address[])": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signatures": "Function signatures", + "_targets": "Address of the destination contract to call" + } + }, + "setMasterCopy(address)": { + "params": { + "_masterCopy": "Address of contract bytecode to factory clone" + } + }, + "token()": { + "returns": { + "_0": "Token used for transfers and approvals" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "unsetAuthFunctionCall(string)": { + "details": "Input expected is the function signature as 'transfer(address,uint256)'", + "params": { + "_signature": "Function signature" + } + }, + "withdraw(uint256)": { + "details": "Escape hatch in case of mistakes or to recover remaining funds", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockManager", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "addTokenDestination(address)": { + "notice": "Adds an address that can be allowed by a token lock to pull funds" + }, + "constructor": { + "notice": "Constructor." + }, + "createTokenLockWallet(address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)": { + "notice": "Creates and fund a new token lock wallet using a minimum proxy" + }, + "deposit(uint256)": { + "notice": "Deposits tokens into the contract" + }, + "getAuthFunctionCallTarget(bytes4)": { + "notice": "Gets the target contract to call for a particular function signature" + }, + "getDeploymentAddress(bytes32,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getDeploymentAddress(bytes32,address,address)": { + "notice": "Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation" + }, + "getTokenDestinations()": { + "notice": "Returns an array of authorized destination addresses" + }, + "isAuthFunctionCall(bytes4)": { + "notice": "Returns true if the function call is authorized" + }, + "isTokenDestination(address)": { + "notice": "Returns True if the address is authorized to be a destination of tokens" + }, + "removeTokenDestination(address)": { + "notice": "Removes an address that can be allowed by a token lock to pull funds" + }, + "setAuthFunctionCall(string,address)": { + "notice": "Sets an authorized function call to target" + }, + "setAuthFunctionCallMany(string[],address[])": { + "notice": "Sets an authorized function call to target in bulk" + }, + "setMasterCopy(address)": { + "notice": "Sets the masterCopy bytecode to use to create clones of TokenLock contracts" + }, + "token()": { + "notice": "Gets the GRT token address" + }, + "unsetAuthFunctionCall(string)": { + "notice": "Unsets an authorized function call to target" + }, + "withdraw(uint256)": { + "notice": "Withdraws tokens from the contract" + } + }, + "notice": "This contract manages a list of authorized function calls and targets that can be called by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts. This contract receives funds to make the process of creating TokenLockWallet contracts easier by distributing them the initial tokens to be managed. The owner can setup a list of token destinations that will be used by TokenLock contracts to approve the pulling of funds, this way in can be guaranteed that only protocol contracts will manipulate users funds.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 672, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 3988, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "authFnCalls", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes4,t_address)" + }, + { + "astId": 3990, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_tokenDestinations", + "offset": 0, + "slot": "2", + "type": "t_struct(AddressSet)2629_storage" + }, + { + "astId": 3992, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "masterCopy", + "offset": 0, + "slot": "4", + "type": "t_address" + }, + { + "astId": 3994, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_token", + "offset": 0, + "slot": "5", + "type": "t_contract(IERC20)1710" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes32)dyn_storage": { + "base": "t_bytes32", + "encoding": "dynamic_array", + "label": "bytes32[]", + "numberOfBytes": "32" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_uint256)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_mapping(t_bytes4,t_address)": { + "encoding": "mapping", + "key": "t_bytes4", + "label": "mapping(bytes4 => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_struct(AddressSet)2629_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.AddressSet", + "members": [ + { + "astId": 2628, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_inner", + "offset": 0, + "slot": "0", + "type": "t_struct(Set)2364_storage" + } + ], + "numberOfBytes": "64" + }, + "t_struct(Set)2364_storage": { + "encoding": "inplace", + "label": "struct EnumerableSet.Set", + "members": [ + { + "astId": 2359, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_values", + "offset": 0, + "slot": "0", + "type": "t_array(t_bytes32)dyn_storage" + }, + { + "astId": 2363, + "contract": "contracts/GraphTokenLockManager.sol:GraphTokenLockManager", + "label": "_indexes", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_uint256)" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/sepolia/GraphTokenLockWallet.json b/packages/token-distribution/deployments/sepolia/GraphTokenLockWallet.json new file mode 100644 index 000000000..312836e89 --- /dev/null +++ b/packages/token-distribution/deployments/sepolia/GraphTokenLockWallet.json @@ -0,0 +1,1101 @@ +{ + "address": "0xd8a03C88984d5669d467aE72Fbb21cD7Ce6E08D4", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "LockCanceled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_oldManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "ManagerUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "TokenDestinationsRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beneficiary", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokensWithdrawn", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "acceptLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "amountPerPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "approveProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "availableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "cancelLock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newBeneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentPeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "duration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "endTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_manager", + "type": "address" + }, + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "address", + "name": "_beneficiary", + "type": "address" + }, + { + "internalType": "address", + "name": "_token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_managedAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_endTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_periods", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_releaseStartTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_vestingCliffTime", + "type": "uint256" + }, + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "_revocable", + "type": "uint8" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isAccepted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isRevoked", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "managedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "manager", + "outputs": [ + { + "internalType": "contract IGraphTokenLockManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "passedPeriods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periodDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "periods", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasableAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "release", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "releasedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revocable", + "outputs": [ + { + "internalType": "enum IGraphTokenLock.Revocability", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "revoke", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokeProtocol", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "revokedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "sinceStartTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "surplusAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalOutstandingAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "usedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vestingCliffTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawSurplus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x416a693b6489bb703b6b3e28d8fbb81d1e245a050e93bb4d671dccb18292eeb3", + "receipt": { + "to": null, + "from": "0x559081D91F5Ff43dfE51A07C216F8E6893805B35", + "contractAddress": "0xd8a03C88984d5669d467aE72Fbb21cD7Ce6E08D4", + "transactionIndex": 26, + "gasUsed": "3942206", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf9b41b792a46f3c8b342c85356b0268526c92dfd758d66ada4c5f2382f0120a5", + "transactionHash": "0x416a693b6489bb703b6b3e28d8fbb81d1e245a050e93bb4d671dccb18292eeb3", + "logs": [], + "blockNumber": 4570363, + "cumulativeGasUsed": "10254368", + "status": 1, + "byzantium": true + }, + "args": [], + "solcInputHash": "095bd30babc75057be19228ca1fd7aa4", + "metadata": "{\"compiler\":{\"version\":\"0.7.3+commit.9bfce1f6\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newBeneficiary\",\"type\":\"address\"}],\"name\":\"BeneficiaryChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"LockCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_oldManager\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"ManagerUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"TokenDestinationsRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensReleased\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beneficiary\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TokensWithdrawn\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"amountPerPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"approveProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"availableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"beneficiary\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelLock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newBeneficiary\",\"type\":\"address\"}],\"name\":\"changeBeneficiary\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"currentTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"duration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"endTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_manager\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_beneficiary\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_managedAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_startTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_endTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_periods\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_releaseStartTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_vestingCliffTime\",\"type\":\"uint256\"},{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"_revocable\",\"type\":\"uint8\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isAccepted\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRevoked\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"managedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"manager\",\"outputs\":[{\"internalType\":\"contract IGraphTokenLockManager\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"passedPeriods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periodDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"periods\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasableAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"release\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releasedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revocable\",\"outputs\":[{\"internalType\":\"enum IGraphTokenLock.Revocability\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revoke\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokeProtocol\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"revokedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newManager\",\"type\":\"address\"}],\"name\":\"setManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"sinceStartTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"startTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"surplusAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalOutstandingAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"usedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestedAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vestingCliffTime\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdrawSurplus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"acceptLock()\":{\"details\":\"Can only be called by the beneficiary\"},\"amountPerPeriod()\":{\"returns\":{\"_0\":\"Amount of tokens available after each period\"}},\"approveProtocol()\":{\"details\":\"Approves all token destinations registered in the manager to pull tokens\"},\"availableAmount()\":{\"details\":\"Implements the step-by-step schedule based on periods for available tokens\",\"returns\":{\"_0\":\"Amount of tokens available according to the schedule\"}},\"cancelLock()\":{\"details\":\"Can only be called by the owner\"},\"changeBeneficiary(address)\":{\"details\":\"Can only be called by the beneficiary\",\"params\":{\"_newBeneficiary\":\"Address of the new beneficiary address\"}},\"currentBalance()\":{\"returns\":{\"_0\":\"Tokens held in the contract\"}},\"currentPeriod()\":{\"returns\":{\"_0\":\"A number that represents the current period\"}},\"currentTime()\":{\"returns\":{\"_0\":\"Current block timestamp\"}},\"duration()\":{\"returns\":{\"_0\":\"Amount of seconds from contract startTime to endTime\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"passedPeriods()\":{\"returns\":{\"_0\":\"A number of periods that passed since the schedule started\"}},\"periodDuration()\":{\"returns\":{\"_0\":\"Duration of each period in seconds\"}},\"releasableAmount()\":{\"details\":\"Considers the schedule, takes into account already released tokens and used amount\",\"returns\":{\"_0\":\"Amount of tokens ready to be released\"}},\"release()\":{\"details\":\"All available releasable tokens are transferred to beneficiary\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner.\"},\"revoke()\":{\"details\":\"Vesting schedule is always calculated based on managed tokens\"},\"revokeProtocol()\":{\"details\":\"Revokes approval to all token destinations in the manager to pull tokens\"},\"setManager(address)\":{\"params\":{\"_newManager\":\"Address of the new manager\"}},\"sinceStartTime()\":{\"details\":\"Returns zero if called before conctract starTime\",\"returns\":{\"_0\":\"Seconds elapsed from contract startTime\"}},\"surplusAmount()\":{\"details\":\"All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\",\"returns\":{\"_0\":\"Amount of tokens considered as surplus\"}},\"totalOutstandingAmount()\":{\"details\":\"Does not consider schedule but just global amounts tracked\",\"returns\":{\"_0\":\"Amount of outstanding tokens for the lifetime of the contract\"}},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"vestedAmount()\":{\"details\":\"Similar to available amount, but is fully vested when contract is non-revocable\",\"returns\":{\"_0\":\"Amount of tokens already vested\"}},\"withdrawSurplus(uint256)\":{\"details\":\"Tokens in the contract over outstanding amount are considered as surplus\",\"params\":{\"_amount\":\"Amount of tokens to withdraw\"}}},\"title\":\"GraphTokenLockWallet\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"acceptLock()\":{\"notice\":\"Beneficiary accepts the lock, the owner cannot retrieve back the tokens\"},\"amountPerPeriod()\":{\"notice\":\"Returns amount available to be released after each period according to schedule\"},\"approveProtocol()\":{\"notice\":\"Approves protocol access of the tokens managed by this contract\"},\"availableAmount()\":{\"notice\":\"Gets the currently available token according to the schedule\"},\"cancelLock()\":{\"notice\":\"Owner cancel the lock and return the balance in the contract\"},\"changeBeneficiary(address)\":{\"notice\":\"Change the beneficiary of funds managed by the contract\"},\"currentBalance()\":{\"notice\":\"Returns the amount of tokens currently held by the contract\"},\"currentPeriod()\":{\"notice\":\"Gets the current period based on the schedule\"},\"currentTime()\":{\"notice\":\"Returns the current block timestamp\"},\"duration()\":{\"notice\":\"Gets duration of contract from start to end in seconds\"},\"passedPeriods()\":{\"notice\":\"Gets the number of periods that passed since the first period\"},\"periodDuration()\":{\"notice\":\"Returns the duration of each period in seconds\"},\"releasableAmount()\":{\"notice\":\"Gets tokens currently available for release\"},\"release()\":{\"notice\":\"Releases tokens based on the configured schedule\"},\"revoke()\":{\"notice\":\"Revokes a vesting schedule and return the unvested tokens to the owner\"},\"revokeProtocol()\":{\"notice\":\"Revokes protocol access of the tokens managed by this contract\"},\"setManager(address)\":{\"notice\":\"Sets a new manager for this contract\"},\"sinceStartTime()\":{\"notice\":\"Gets time elapsed since the start of the contract\"},\"surplusAmount()\":{\"notice\":\"Gets surplus amount in the contract based on outstanding amount to release\"},\"totalOutstandingAmount()\":{\"notice\":\"Gets the outstanding amount yet to be released based on the whole contract lifetime\"},\"vestedAmount()\":{\"notice\":\"Gets the amount of currently vested tokens\"},\"withdrawSurplus(uint256)\":{\"notice\":\"Withdraws surplus, unmanaged tokens from the contract\"}},\"notice\":\"This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/GraphTokenLockWallet.sol\":\"GraphTokenLockWallet\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\\n * checks.\\n *\\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\\n * in bugs, because programmers usually assume that an overflow raises an\\n * error, which is the standard behavior in high level programming languages.\\n * `SafeMath` restores this intuition by reverting the transaction when an\\n * operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n uint256 c = a + b;\\n require(c >= a, \\\"SafeMath: addition overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b <= a, \\\"SafeMath: subtraction overflow\\\");\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n if (a == 0) return 0;\\n uint256 c = a * b;\\n require(c / a == b, \\\"SafeMath: multiplication overflow\\\");\\n return c;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: division by zero\\\");\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n require(b > 0, \\\"SafeMath: modulo by zero\\\");\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryDiv}.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n}\\n\",\"keccak256\":\"0xcc78a17dd88fa5a2edc60c8489e2f405c0913b377216a5b26b35656b2d0dab52\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x5f02220344881ce43204ae4a6281145a67bc52c2bb1290a791857df3d19d78f5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.0 <0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"../../math/SafeMath.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using SafeMath for uint256;\\n using Address for address;\\n\\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n // solhint-disable-next-line max-line-length\\n require((value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) { // Return data is optional\\n // solhint-disable-next-line max-line-length\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf12dfbe97e6276980b83d2830bb0eb75e0cf4f3e626c2471137f82158ae6a0fc\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\n (bool success, ) = recipient.call{ value: amount }(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain`call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/GraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\\\";\\n\\nimport { Ownable as OwnableInitializable } from \\\"./Ownable.sol\\\";\\nimport \\\"./MathUtils.sol\\\";\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\n/**\\n * @title GraphTokenLock\\n * @notice Contract that manages an unlocking schedule of tokens.\\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\\n * they can only be released under certain time conditions.\\n *\\n * This contract implements a release scheduled based on periods and tokens are released in steps\\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\\n * It also supports revocation to be used for vesting schedules.\\n *\\n * The contract supports receiving extra funds than the managed tokens ones that can be\\n * withdrawn by the beneficiary at any time.\\n *\\n * A releaseStartTime parameter is included to override the default release schedule and\\n * perform the first release on the configured time. After that it will continue with the\\n * default schedule.\\n */\\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\\n using SafeMath for uint256;\\n using SafeERC20 for IERC20;\\n\\n uint256 private constant MIN_PERIOD = 1;\\n\\n // -- State --\\n\\n IERC20 public token;\\n address public beneficiary;\\n\\n // Configuration\\n\\n // Amount of tokens managed by the contract schedule\\n uint256 public managedAmount;\\n\\n uint256 public startTime; // Start datetime (in unixtimestamp)\\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\\n uint256 public periods; // Number of vesting/release periods\\n\\n // First release date for tokens (in unixtimestamp)\\n // If set, no tokens will be released before releaseStartTime ignoring\\n // the amount to release each period\\n uint256 public releaseStartTime;\\n // A cliff set a date to which a beneficiary needs to get to vest\\n // all preceding periods\\n uint256 public vestingCliffTime;\\n Revocability public revocable; // Whether to use vesting for locked funds\\n\\n // State\\n\\n bool public isRevoked;\\n bool public isInitialized;\\n bool public isAccepted;\\n uint256 public releasedAmount;\\n uint256 public revokedAmount;\\n\\n // -- Events --\\n\\n event TokensReleased(address indexed beneficiary, uint256 amount);\\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\\n event TokensRevoked(address indexed beneficiary, uint256 amount);\\n event BeneficiaryChanged(address newBeneficiary);\\n event LockAccepted();\\n event LockCanceled();\\n\\n /**\\n * @dev Only allow calls from the beneficiary of the contract\\n */\\n modifier onlyBeneficiary() {\\n require(msg.sender == beneficiary, \\\"!auth\\\");\\n _;\\n }\\n\\n /**\\n * @notice Initializes the contract\\n * @param _owner Address of the contract owner\\n * @param _beneficiary Address of the beneficiary of locked tokens\\n * @param _managedAmount Amount of tokens to be managed by the lock contract\\n * @param _startTime Start time of the release schedule\\n * @param _endTime End time of the release schedule\\n * @param _periods Number of periods between start time and end time\\n * @param _releaseStartTime Override time for when the releases start\\n * @param _vestingCliffTime Override time for when the vesting start\\n * @param _revocable Whether the contract is revocable\\n */\\n function _initialize(\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) internal {\\n require(!isInitialized, \\\"Already initialized\\\");\\n require(_owner != address(0), \\\"Owner cannot be zero\\\");\\n require(_beneficiary != address(0), \\\"Beneficiary cannot be zero\\\");\\n require(_token != address(0), \\\"Token cannot be zero\\\");\\n require(_managedAmount > 0, \\\"Managed tokens cannot be zero\\\");\\n require(_startTime != 0, \\\"Start time must be set\\\");\\n require(_startTime < _endTime, \\\"Start time > end time\\\");\\n require(_periods >= MIN_PERIOD, \\\"Periods cannot be below minimum\\\");\\n require(_revocable != Revocability.NotSet, \\\"Must set a revocability option\\\");\\n require(_releaseStartTime < _endTime, \\\"Release start time must be before end time\\\");\\n require(_vestingCliffTime < _endTime, \\\"Cliff time must be before end time\\\");\\n\\n isInitialized = true;\\n\\n OwnableInitializable._initialize(_owner);\\n beneficiary = _beneficiary;\\n token = IERC20(_token);\\n\\n managedAmount = _managedAmount;\\n\\n startTime = _startTime;\\n endTime = _endTime;\\n periods = _periods;\\n\\n // Optionals\\n releaseStartTime = _releaseStartTime;\\n vestingCliffTime = _vestingCliffTime;\\n revocable = _revocable;\\n }\\n\\n /**\\n * @notice Change the beneficiary of funds managed by the contract\\n * @dev Can only be called by the beneficiary\\n * @param _newBeneficiary Address of the new beneficiary address\\n */\\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\\n require(_newBeneficiary != address(0), \\\"Empty beneficiary\\\");\\n beneficiary = _newBeneficiary;\\n emit BeneficiaryChanged(_newBeneficiary);\\n }\\n\\n /**\\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\\n * @dev Can only be called by the beneficiary\\n */\\n function acceptLock() external onlyBeneficiary {\\n isAccepted = true;\\n emit LockAccepted();\\n }\\n\\n /**\\n * @notice Owner cancel the lock and return the balance in the contract\\n * @dev Can only be called by the owner\\n */\\n function cancelLock() external onlyOwner {\\n require(isAccepted == false, \\\"Cannot cancel accepted contract\\\");\\n\\n token.safeTransfer(owner(), currentBalance());\\n\\n emit LockCanceled();\\n }\\n\\n // -- Balances --\\n\\n /**\\n * @notice Returns the amount of tokens currently held by the contract\\n * @return Tokens held in the contract\\n */\\n function currentBalance() public view override returns (uint256) {\\n return token.balanceOf(address(this));\\n }\\n\\n // -- Time & Periods --\\n\\n /**\\n * @notice Returns the current block timestamp\\n * @return Current block timestamp\\n */\\n function currentTime() public view override returns (uint256) {\\n return block.timestamp;\\n }\\n\\n /**\\n * @notice Gets duration of contract from start to end in seconds\\n * @return Amount of seconds from contract startTime to endTime\\n */\\n function duration() public view override returns (uint256) {\\n return endTime.sub(startTime);\\n }\\n\\n /**\\n * @notice Gets time elapsed since the start of the contract\\n * @dev Returns zero if called before conctract starTime\\n * @return Seconds elapsed from contract startTime\\n */\\n function sinceStartTime() public view override returns (uint256) {\\n uint256 current = currentTime();\\n if (current <= startTime) {\\n return 0;\\n }\\n return current.sub(startTime);\\n }\\n\\n /**\\n * @notice Returns amount available to be released after each period according to schedule\\n * @return Amount of tokens available after each period\\n */\\n function amountPerPeriod() public view override returns (uint256) {\\n return managedAmount.div(periods);\\n }\\n\\n /**\\n * @notice Returns the duration of each period in seconds\\n * @return Duration of each period in seconds\\n */\\n function periodDuration() public view override returns (uint256) {\\n return duration().div(periods);\\n }\\n\\n /**\\n * @notice Gets the current period based on the schedule\\n * @return A number that represents the current period\\n */\\n function currentPeriod() public view override returns (uint256) {\\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\\n }\\n\\n /**\\n * @notice Gets the number of periods that passed since the first period\\n * @return A number of periods that passed since the schedule started\\n */\\n function passedPeriods() public view override returns (uint256) {\\n return currentPeriod().sub(MIN_PERIOD);\\n }\\n\\n // -- Locking & Release Schedule --\\n\\n /**\\n * @notice Gets the currently available token according to the schedule\\n * @dev Implements the step-by-step schedule based on periods for available tokens\\n * @return Amount of tokens available according to the schedule\\n */\\n function availableAmount() public view override returns (uint256) {\\n uint256 current = currentTime();\\n\\n // Before contract start no funds are available\\n if (current < startTime) {\\n return 0;\\n }\\n\\n // After contract ended all funds are available\\n if (current > endTime) {\\n return managedAmount;\\n }\\n\\n // Get available amount based on period\\n return passedPeriods().mul(amountPerPeriod());\\n }\\n\\n /**\\n * @notice Gets the amount of currently vested tokens\\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\\n * @return Amount of tokens already vested\\n */\\n function vestedAmount() public view override returns (uint256) {\\n // If non-revocable it is fully vested\\n if (revocable == Revocability.Disabled) {\\n return managedAmount;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n return availableAmount();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule and takes into account already released tokens\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view virtual override returns (uint256) {\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n uint256 releasable = availableAmount().sub(releasedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\\n * @dev Does not consider schedule but just global amounts tracked\\n * @return Amount of outstanding tokens for the lifetime of the contract\\n */\\n function totalOutstandingAmount() public view override returns (uint256) {\\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\\n }\\n\\n /**\\n * @notice Gets surplus amount in the contract based on outstanding amount to release\\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\\n * @return Amount of tokens considered as surplus\\n */\\n function surplusAmount() public view override returns (uint256) {\\n uint256 balance = currentBalance();\\n uint256 outstandingAmount = totalOutstandingAmount();\\n if (balance > outstandingAmount) {\\n return balance.sub(outstandingAmount);\\n }\\n return 0;\\n }\\n\\n // -- Value Transfer --\\n\\n /**\\n * @notice Releases tokens based on the configured schedule\\n * @dev All available releasable tokens are transferred to beneficiary\\n */\\n function release() external override onlyBeneficiary {\\n uint256 amountToRelease = releasableAmount();\\n require(amountToRelease > 0, \\\"No available releasable amount\\\");\\n\\n releasedAmount = releasedAmount.add(amountToRelease);\\n\\n token.safeTransfer(beneficiary, amountToRelease);\\n\\n emit TokensReleased(beneficiary, amountToRelease);\\n }\\n\\n /**\\n * @notice Withdraws surplus, unmanaged tokens from the contract\\n * @dev Tokens in the contract over outstanding amount are considered as surplus\\n * @param _amount Amount of tokens to withdraw\\n */\\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\\n require(_amount > 0, \\\"Amount cannot be zero\\\");\\n require(surplusAmount() >= _amount, \\\"Amount requested > surplus available\\\");\\n\\n token.safeTransfer(beneficiary, _amount);\\n\\n emit TokensWithdrawn(beneficiary, _amount);\\n }\\n\\n /**\\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\\n * @dev Vesting schedule is always calculated based on managed tokens\\n */\\n function revoke() external override onlyOwner {\\n require(revocable == Revocability.Enabled, \\\"Contract is non-revocable\\\");\\n require(isRevoked == false, \\\"Already revoked\\\");\\n\\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\\n require(unvestedAmount > 0, \\\"No available unvested amount\\\");\\n\\n revokedAmount = unvestedAmount;\\n isRevoked = true;\\n\\n token.safeTransfer(owner(), unvestedAmount);\\n\\n emit TokensRevoked(beneficiary, unvestedAmount);\\n }\\n}\\n\",\"keccak256\":\"0xd89470956a476c2fcf4a09625775573f95ba2c60a57fe866d90f65de1bcf5f2d\",\"license\":\"MIT\"},\"contracts/GraphTokenLockWallet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\nimport \\\"@openzeppelin/contracts/math/SafeMath.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./GraphTokenLock.sol\\\";\\nimport \\\"./IGraphTokenLockManager.sol\\\";\\n\\n/**\\n * @title GraphTokenLockWallet\\n * @notice This contract is built on top of the base GraphTokenLock functionality.\\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\\n * on specific contracts.\\n *\\n * The idea is that supporters with locked tokens can participate in the protocol\\n * but disallow any release before the vesting/lock schedule.\\n * The beneficiary can issue authorized function calls to this contract that will\\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\\n * The function calls allowed are queried to the GraphTokenLockManager, this way\\n * the same configuration can be shared for all the created lock wallet contracts.\\n *\\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\\n * with any of this contract functions.\\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\\n * the maximum amount of tokens is authorized.\\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\\n */\\ncontract GraphTokenLockWallet is GraphTokenLock {\\n using SafeMath for uint256;\\n\\n // -- State --\\n\\n IGraphTokenLockManager public manager;\\n uint256 public usedAmount;\\n\\n // -- Events --\\n\\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\\n event TokenDestinationsApproved();\\n event TokenDestinationsRevoked();\\n\\n // Initializer\\n function initialize(\\n address _manager,\\n address _owner,\\n address _beneficiary,\\n address _token,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n Revocability _revocable\\n ) external {\\n _initialize(\\n _owner,\\n _beneficiary,\\n _token,\\n _managedAmount,\\n _startTime,\\n _endTime,\\n _periods,\\n _releaseStartTime,\\n _vestingCliffTime,\\n _revocable\\n );\\n _setManager(_manager);\\n }\\n\\n // -- Admin --\\n\\n /**\\n * @notice Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function setManager(address _newManager) external onlyOwner {\\n _setManager(_newManager);\\n }\\n\\n /**\\n * @dev Sets a new manager for this contract\\n * @param _newManager Address of the new manager\\n */\\n function _setManager(address _newManager) internal {\\n require(_newManager != address(0), \\\"Manager cannot be empty\\\");\\n require(Address.isContract(_newManager), \\\"Manager must be a contract\\\");\\n\\n address oldManager = address(manager);\\n manager = IGraphTokenLockManager(_newManager);\\n\\n emit ManagerUpdated(oldManager, _newManager);\\n }\\n\\n // -- Beneficiary --\\n\\n /**\\n * @notice Approves protocol access of the tokens managed by this contract\\n * @dev Approves all token destinations registered in the manager to pull tokens\\n */\\n function approveProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe because we are using the max uint256 value\\n token.approve(dstList[i], type(uint256).max);\\n }\\n emit TokenDestinationsApproved();\\n }\\n\\n /**\\n * @notice Revokes protocol access of the tokens managed by this contract\\n * @dev Revokes approval to all token destinations in the manager to pull tokens\\n */\\n function revokeProtocol() external onlyBeneficiary {\\n address[] memory dstList = manager.getTokenDestinations();\\n for (uint256 i = 0; i < dstList.length; i++) {\\n // Note this is only safe cause we're using 0 as the amount\\n token.approve(dstList[i], 0);\\n }\\n emit TokenDestinationsRevoked();\\n }\\n\\n /**\\n * @notice Gets tokens currently available for release\\n * @dev Considers the schedule, takes into account already released tokens and used amount\\n * @return Amount of tokens ready to be released\\n */\\n function releasableAmount() public view override returns (uint256) {\\n if (revocable == Revocability.Disabled) {\\n return super.releasableAmount();\\n }\\n\\n // -- Revocability enabled logic\\n // This needs to deal with additional considerations for when tokens are used in the protocol\\n\\n // If a release start time is set no tokens are available for release before this date\\n // If not set it follows the default schedule and tokens are available on\\n // the first period passed\\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\\n return 0;\\n }\\n\\n // Vesting cliff is activated and it has not passed means nothing is vested yet\\n // so funds cannot be released\\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\\n return 0;\\n }\\n\\n // A beneficiary can never have more releasable tokens than the contract balance\\n // We consider the `usedAmount` in the protocol as part of the calculations\\n // the beneficiary should not release funds that are used.\\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\\n return MathUtils.min(currentBalance(), releasable);\\n }\\n\\n /**\\n * @notice Forward authorized contract calls to protocol contracts\\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\\n */\\n // solhint-disable-next-line no-complex-fallback\\n fallback() external payable {\\n // Only beneficiary can forward calls\\n require(msg.sender == beneficiary, \\\"Unauthorized caller\\\");\\n require(msg.value == 0, \\\"ETH transfers not supported\\\");\\n\\n // Function call validation\\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\\n require(_target != address(0), \\\"Unauthorized function\\\");\\n\\n uint256 oldBalance = currentBalance();\\n\\n // Call function with data\\n Address.functionCall(_target, msg.data);\\n\\n // Tracked used tokens in the protocol\\n // We do this check after balances were updated by the forwarded call\\n // Check is only enforced for revocable contracts to save some gas\\n if (revocable == Revocability.Enabled) {\\n // Track contract balance change\\n uint256 newBalance = currentBalance();\\n if (newBalance < oldBalance) {\\n // Outflow\\n uint256 diff = oldBalance.sub(newBalance);\\n usedAmount = usedAmount.add(diff);\\n } else {\\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\\n // underflow. We set it to zero in that case.\\n uint256 diff = newBalance.sub(oldBalance);\\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\\n }\\n require(usedAmount <= vestedAmount(), \\\"Cannot use more tokens than vested amount\\\");\\n }\\n }\\n\\n /**\\n * @notice Receive function that always reverts.\\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\\n */\\n receive() external payable {\\n revert(\\\"Bad call\\\");\\n }\\n}\\n\",\"keccak256\":\"0x976c2ba4c1503a81ea02bd84539c516e99af611ff767968ee25456b50a6deb7b\",\"license\":\"MIT\"},\"contracts/IGraphTokenLock.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IGraphTokenLock {\\n enum Revocability {\\n NotSet,\\n Enabled,\\n Disabled\\n }\\n\\n // -- Balances --\\n\\n function currentBalance() external view returns (uint256);\\n\\n // -- Time & Periods --\\n\\n function currentTime() external view returns (uint256);\\n\\n function duration() external view returns (uint256);\\n\\n function sinceStartTime() external view returns (uint256);\\n\\n function amountPerPeriod() external view returns (uint256);\\n\\n function periodDuration() external view returns (uint256);\\n\\n function currentPeriod() external view returns (uint256);\\n\\n function passedPeriods() external view returns (uint256);\\n\\n // -- Locking & Release Schedule --\\n\\n function availableAmount() external view returns (uint256);\\n\\n function vestedAmount() external view returns (uint256);\\n\\n function releasableAmount() external view returns (uint256);\\n\\n function totalOutstandingAmount() external view returns (uint256);\\n\\n function surplusAmount() external view returns (uint256);\\n\\n // -- Value Transfer --\\n\\n function release() external;\\n\\n function withdrawSurplus(uint256 _amount) external;\\n\\n function revoke() external;\\n}\\n\",\"keccak256\":\"0xceb9d258276fe25ec858191e1deae5778f1b2f612a669fb7b37bab1a064756ab\",\"license\":\"MIT\"},\"contracts/IGraphTokenLockManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\npragma experimental ABIEncoderV2;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport \\\"./IGraphTokenLock.sol\\\";\\n\\ninterface IGraphTokenLockManager {\\n // -- Factory --\\n\\n function setMasterCopy(address _masterCopy) external;\\n\\n function createTokenLockWallet(\\n address _owner,\\n address _beneficiary,\\n uint256 _managedAmount,\\n uint256 _startTime,\\n uint256 _endTime,\\n uint256 _periods,\\n uint256 _releaseStartTime,\\n uint256 _vestingCliffTime,\\n IGraphTokenLock.Revocability _revocable\\n ) external;\\n\\n // -- Funds Management --\\n\\n function token() external returns (IERC20);\\n\\n function deposit(uint256 _amount) external;\\n\\n function withdraw(uint256 _amount) external;\\n\\n // -- Allowed Funds Destinations --\\n\\n function addTokenDestination(address _dst) external;\\n\\n function removeTokenDestination(address _dst) external;\\n\\n function isTokenDestination(address _dst) external view returns (bool);\\n\\n function getTokenDestinations() external view returns (address[] memory);\\n\\n // -- Function Call Authorization --\\n\\n function setAuthFunctionCall(string calldata _signature, address _target) external;\\n\\n function unsetAuthFunctionCall(string calldata _signature) external;\\n\\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\\n\\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\\n\\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2d78d41909a6de5b316ac39b100ea087a8f317cf306379888a045523e15c4d9a\",\"license\":\"MIT\"},\"contracts/MathUtils.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\nlibrary MathUtils {\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n}\\n\",\"keccak256\":\"0xe2512e1da48bc8363acd15f66229564b02d66706665d7da740604566913c1400\",\"license\":\"MIT\"},\"contracts/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.7.3;\\n\\n/**\\n * @dev Contract module which provides a basic access control mechanism, where\\n * there is an account (an owner) that can be granted exclusive access to\\n * specific functions.\\n *\\n * The owner account will be passed on initialization of the contract. This\\n * can later be changed with {transferOwnership}.\\n *\\n * This module is used through inheritance. It will make available the modifier\\n * `onlyOwner`, which can be applied to your functions to restrict their use to\\n * the owner.\\n */\\ncontract Ownable {\\n /// @dev Owner of the contract, can be retrieved with the public owner() function\\n address private _owner;\\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\\n /// to allow adding variables here without breaking the proxy storage layout\\n uint256[50] private __gap;\\n\\n /// @dev Emitted when ownership of the contract is transferred\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev Initializes the contract setting the deployer as the initial owner.\\n */\\n function _initialize(address owner) internal {\\n _owner = owner;\\n emit OwnershipTransferred(address(0), owner);\\n }\\n\\n /**\\n * @dev Returns the address of the current owner.\\n */\\n function owner() public view returns (address) {\\n return _owner;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(_owner == msg.sender, \\\"Ownable: caller is not the owner\\\");\\n _;\\n }\\n\\n /**\\n * @dev Leaves the contract without owner. It will not be possible to call\\n * `onlyOwner` functions anymore. Can only be called by the current owner.\\n *\\n * NOTE: Renouncing ownership will leave the contract without an owner,\\n * thereby removing any functionality that is only available to the owner.\\n */\\n function renounceOwnership() external virtual onlyOwner {\\n emit OwnershipTransferred(_owner, address(0));\\n _owner = address(0);\\n }\\n\\n /**\\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\\n * Can only be called by the current owner.\\n */\\n function transferOwnership(address newOwner) external virtual onlyOwner {\\n require(newOwner != address(0), \\\"Ownable: new owner is the zero address\\\");\\n emit OwnershipTransferred(_owner, newOwner);\\n _owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0xe8750687082e8e24b620dbf58c3a08eee591ed7b4d5a3e13cc93554ec647fd09\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506146bb806100206000396000f3fe6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610b93578063e8dda6f514610bbc578063e97d87d514610be7578063ebbab99214610c12578063f2fde38b14610c3d578063fc0c546a14610c6657610295565b8063bc0163c114610ac0578063bd896dcb14610aeb578063ce845d1d14610b14578063d0ebdbe714610b3f578063d18e81b314610b6857610295565b806391f7cfb9116100fd57806391f7cfb9146109ff578063a4caeb4214610a2a578063b0d1818c14610a55578063b470aade14610a7e578063b6549f7514610aa957610295565b806386d00e021461095057806386d1a69f1461097b578063872a7810146109925780638a5bdf5c146109bd5780638da5cb5b146109d457610295565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108765780635b940081146108a157806360e79944146108cc578063715018a6146108e357806378e97925146108fa5780637bdf05af1461092557610295565b8063392e53cd1461079f578063398057a3146107ca57806344b1231f146107f557806345d30a1714610820578063481c6a751461084b57610295565b80632a627814116102195780632a627814146106dc5780632bc9ed02146106f35780633197cbb61461071e57806337aeb0861461074957806338af3eed1461077457610295565b8063029c6c9f1461061957806306040618146106445780630b80f7771461066f5780630dff24d5146106865780630fb5a6b4146106b157610295565b36610295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028c90613fb9565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c90614199565b60405180910390fd5b60003414610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035f90613fd9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103e99190613f2b565b60206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043991906131a5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a290614299565b60405180910390fd5b60006104b5610c91565b9050610506826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d43565b506001600281111561051457fe5b603b60009054906101000a900460ff16600281111561052f57fe5b141561061557600061053f610c91565b90508181101561058157600061055e8284610d8d90919063ffffffff16565b905061057581603f54610ddd90919063ffffffff16565b603f81905550506105c7565b60006105968383610d8d90919063ffffffff16565b9050603f548110156105bc576105b781603f54610d8d90919063ffffffff16565b6105bf565b60005b603f81905550505b6105cf610e32565b603f541115610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060a906141f9565b60405180910390fd5b505b5050005b34801561062557600080fd5b5061062e610ea1565b60405161063b9190614439565b60405180910390f35b34801561065057600080fd5b50610659610ebf565b6040516106669190614439565b60405180910390f35b34801561067b57600080fd5b50610684610efa565b005b34801561069257600080fd5b5061069b611067565b6040516106a89190614439565b60405180910390f35b3480156106bd57600080fd5b506106c66110ae565b6040516106d39190614439565b60405180910390f35b3480156106e857600080fd5b506106f16110cc565b005b3480156106ff57600080fd5b50610708611331565b6040516107159190613f10565b60405180910390f35b34801561072a57600080fd5b50610733611344565b6040516107409190614439565b60405180910390f35b34801561075557600080fd5b5061075e61134a565b60405161076b9190614439565b60405180910390f35b34801561078057600080fd5b50610789611350565b6040516107969190613ea3565b60405180910390f35b3480156107ab57600080fd5b506107b4611376565b6040516107c19190613f10565b60405180910390f35b3480156107d657600080fd5b506107df611389565b6040516107ec9190614439565b60405180910390f35b34801561080157600080fd5b5061080a610e32565b6040516108179190614439565b60405180910390f35b34801561082c57600080fd5b5061083561138f565b6040516108429190614439565b60405180910390f35b34801561085757600080fd5b50610860611395565b60405161086d9190613f61565b60405180910390f35b34801561088257600080fd5b5061088b6113bb565b6040516108989190613f10565b60405180910390f35b3480156108ad57600080fd5b506108b66113ce565b6040516108c39190614439565b60405180910390f35b3480156108d857600080fd5b506108e16114d9565b005b3480156108ef57600080fd5b506108f861171f565b005b34801561090657600080fd5b5061090f61186b565b60405161091c9190614439565b60405180910390f35b34801561093157600080fd5b5061093a611871565b6040516109479190614439565b60405180910390f35b34801561095c57600080fd5b506109656118ad565b6040516109729190614439565b60405180910390f35b34801561098757600080fd5b506109906118b3565b005b34801561099e57600080fd5b506109a7611a8f565b6040516109b49190613f7c565b60405180910390f35b3480156109c957600080fd5b506109d2611aa2565b005b3480156109e057600080fd5b506109e9611b7b565b6040516109f69190613ea3565b60405180910390f35b348015610a0b57600080fd5b50610a14611ba4565b604051610a219190614439565b60405180910390f35b348015610a3657600080fd5b50610a3f611c02565b604051610a4c9190614439565b60405180910390f35b348015610a6157600080fd5b50610a7c6004803603810190610a779190613328565b611c08565b005b348015610a8a57600080fd5b50610a93611e07565b604051610aa09190614439565b60405180910390f35b348015610ab557600080fd5b50610abe611e2a565b005b348015610acc57600080fd5b50610ad56120c2565b604051610ae29190614439565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d91906131ce565b6120f4565b005b348015610b2057600080fd5b50610b29610c91565b604051610b369190614439565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061317c565b61211c565b005b348015610b7457600080fd5b50610b7d6121b6565b604051610b8a9190614439565b60405180910390f35b348015610b9f57600080fd5b50610bba6004803603810190610bb5919061317c565b6121be565b005b348015610bc857600080fd5b50610bd1612339565b604051610bde9190614439565b60405180910390f35b348015610bf357600080fd5b50610bfc61233f565b604051610c099190614439565b60405180910390f35b348015610c1e57600080fd5b50610c27612345565b604051610c349190614439565b60405180910390f35b348015610c4957600080fd5b50610c646004803603810190610c5f919061317c565b612367565b005b348015610c7257600080fd5b50610c7b612522565b604051610c889190613f46565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cee9190613ea3565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613351565b905090565b6060610d8583836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b600082821115610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc9906140f9565b60405180910390fd5b818303905092915050565b600080828401905083811015610e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1f90614079565b60405180910390fd5b8091505092915050565b6000600280811115610e4057fe5b603b60009054906101000a900460ff166002811115610e5b57fe5b1415610e6b576035549050610e9e565b6000603a54118015610e855750603a54610e836121b6565b105b15610e935760009050610e9e565b610e9b611ba4565b90505b90565b6000610eba60385460355461256090919063ffffffff16565b905090565b6000610ef56001610ee7610ed1611e07565b610ed9611871565b61256090919063ffffffff16565b610ddd90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7f90614259565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514610fde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fd5906140d9565b60405180910390fd5b611039610fe9611b7b565b610ff1610c91565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611072610c91565b9050600061107e6120c2565b9050808211156110a45761109b8183610d8d90919063ffffffff16565b925050506110ab565b6000925050505b90565b60006110c7603654603754610d8d90919063ffffffff16565b905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461115c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115390614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111c657600080fd5b505afa1580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061120391906132be565b905060005b815181101561130157603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061125b57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b81526004016112a1929190613ee7565b602060405180830381600087803b1580156112bb57600080fd5b505af11580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f391906132ff565b508080600101915050611208565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156113dc57fe5b603b60009054906101000a900460ff1660028111156113f757fe5b141561140c5761140561263c565b90506114d6565b600060395411801561142657506039546114246121b6565b105b1561143457600090506114d6565b6001600281111561144157fe5b603b60009054906101000a900460ff16600281111561145c57fe5b14801561146b57506000603a54115b801561147f5750603a5461147d6121b6565b105b1561148d57600090506114d6565b60006114bf603f546114b1603c546114a3611ba4565b610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b90506114d26114cc610c91565b826126f6565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115d357600080fd5b505afa1580156115e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061161091906132be565b905060005b81518110156116ef57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061166857fe5b602002602001015160006040518363ffffffff1660e01b815260040161168f929190613ebe565b602060405180830381600087803b1580156116a957600080fd5b505af11580156116bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e191906132ff565b508080600101915050611615565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a490614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b60008061187c6121b6565b905060365481116118915760009150506118aa565b6118a660365482610d8d90919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90614359565b60405180910390fd5b600061194d6113ce565b905060008111611992576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611989906143b9565b60405180910390fd5b6119a781603c54610ddd90919063ffffffff16565b603c81905550611a1c603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611a849190614439565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2990614359565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611baf6121b6565b9050603654811015611bc5576000915050611bff565b603754811115611bda57603554915050611bff565b611bfb611be5610ea1565b611bed612345565b61270f90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8f90614359565b60405180910390fd5b60008111611cdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd2906141d9565b60405180910390fd5b80611ce4611067565b1015611d25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1c906142d9565b60405180910390fd5b611d94603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611dfc9190614439565b60405180910390a250565b6000611e25603854611e176110ae565b61256090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90614259565b60405180910390fd5b60016002811115611ec557fe5b603b60009054906101000a900460ff166002811115611ee057fe5b14611f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1790614319565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90614419565b60405180910390fd5b6000611f94611f83610e32565b603554610d8d90919063ffffffff16565b905060008111611fd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd090614099565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061204f612006611b7b565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516120b79190614439565b60405180910390a250565b60006120ef603d546120e1603c54603554610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b905090565b6121068a8a8a8a8a8a8a8a8a8a61277f565b61210f8b612c09565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146121aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a190614259565b60405180910390fd5b6121b381612c09565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461224e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224590614359565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b590614179565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d8160405161232e9190613ea3565b60405180910390a150565b603f5481565b60395481565b60006123626001612354610ebf565b610d8d90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ec90614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245c90614059565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606125578484600085612d87565b90509392505050565b60008082116125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259b90614159565b60405180910390fd5b8183816125ad57fe5b04905092915050565b6126378363a9059cbb60e01b84846040516024016125d5929190613ee7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612e9c565b505050565b60008060395411801561265757506039546126556121b6565b105b1561266557600090506126f3565b6001600281111561267257fe5b603b60009054906101000a900460ff16600281111561268d57fe5b14801561269c57506000603a54115b80156126b05750603a546126ae6121b6565b105b156126be57600090506126f3565b60006126dc603c546126ce611ba4565b610d8d90919063ffffffff16565b90506126ef6126e9610c91565b826126f6565b9150505b90565b60008183106127055781612707565b825b905092915050565b6000808314156127225760009050612779565b600082840290508284828161273357fe5b0414612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90614239565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff16156127cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c6906142f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561283f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612836906140b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128a6906143f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561291f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612916906143d9565b60405180910390fd5b60008711612962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295990614139565b60405180910390fd5b60008614156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299d90614279565b60405180910390fd5b8486106129e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129df90614019565b60405180910390fd5b6001841015612a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2390614219565b60405180910390fd5b60006002811115612a3957fe5b816002811115612a4557fe5b1415612a86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7d90614039565b60405180910390fd5b848310612ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612abf90614379565b60405180910390fd5b848210612b0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0190613ff9565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612b2e8a612f63565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612bf857fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7090614339565b60405180910390fd5b612c8281613001565b612cc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb8906141b9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015612dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dc390614119565b60405180910390fd5b612dd585613001565b612e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0b906142b9565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051612e3e9190613e8c565b60006040518083038185875af1925050503d8060008114612e7b576040519150601f19603f3d011682016040523d82523d6000602084013e612e80565b606091505b5091509150612e90828286613014565b92505050949350505050565b6060612efe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b9050600081511115612f5e5780806020019051810190612f1e91906132ff565b612f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5490614399565b60405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b6060831561302457829050613074565b6000835111156130375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b9190613f97565b60405180910390fd5b9392505050565b60008135905061308a81614630565b92915050565b60008151905061309f81614630565b92915050565b600082601f8301126130b657600080fd5b81516130c96130c482614485565b614454565b915081818352602084019350602081019050838560208402820111156130ee57600080fd5b60005b8381101561311e57816131048882613090565b8452602084019350602083019250506001810190506130f1565b5050505092915050565b60008151905061313781614647565b92915050565b60008135905061314c8161465e565b92915050565b6000813590506131618161466e565b92915050565b6000815190506131768161466e565b92915050565b60006020828403121561318e57600080fd5b600061319c8482850161307b565b91505092915050565b6000602082840312156131b757600080fd5b60006131c584828501613090565b91505092915050565b60008060008060008060008060008060006101608c8e0312156131f057600080fd5b60006131fe8e828f0161307b565b9b5050602061320f8e828f0161307b565b9a505060406132208e828f0161307b565b99505060606132318e828f0161307b565b98505060806132428e828f01613152565b97505060a06132538e828f01613152565b96505060c06132648e828f01613152565b95505060e06132758e828f01613152565b9450506101006132878e828f01613152565b9350506101206132998e828f01613152565b9250506101406132ab8e828f0161313d565b9150509295989b509295989b9093969950565b6000602082840312156132d057600080fd5b600082015167ffffffffffffffff8111156132ea57600080fd5b6132f6848285016130a5565b91505092915050565b60006020828403121561331157600080fd5b600061331f84828501613128565b91505092915050565b60006020828403121561333a57600080fd5b600061334884828501613152565b91505092915050565b60006020828403121561336357600080fd5b600061337184828501613167565b91505092915050565b613383816144e3565b82525050565b613392816144f5565b82525050565b6133a181614501565b82525050565b60006133b2826144b1565b6133bc81856144c7565b93506133cc8185602086016145d6565b80840191505092915050565b6133e18161456a565b82525050565b6133f08161458e565b82525050565b6133ff816145b2565b82525050565b61340e816145c4565b82525050565b600061341f826144bc565b61342981856144d2565b93506134398185602086016145d6565b6134428161460b565b840191505092915050565b600061345a6008836144d2565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b600061349a601b836144d2565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b60006134da6022836144d2565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135406015836144d2565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b6000613580601e836144d2565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006135c06026836144d2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613626601b836144d2565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000613666601c836144d2565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006136a66014836144d2565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006136e6601f836144d2565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613726601e836144d2565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006137666026836144d2565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cc601d836144d2565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b600061380c601a836144d2565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b600061384c6011836144d2565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b600061388c6013836144d2565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b60006138cc601a836144d2565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b600061390c6015836144d2565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b600061394c6029836144d2565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b60006139b2601f836144d2565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b60006139f26021836144d2565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a586020836144d2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613a986016836144d2565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613ad86015836144d2565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613b18601d836144d2565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613b586024836144d2565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bbe6013836144d2565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613bfe6019836144d2565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613c3e6017836144d2565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613c7e6005836144d2565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613cbe602a836144d2565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d24602a836144d2565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d8a601e836144d2565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b6000613dca6014836144d2565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613e0a601a836144d2565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000613e4a600f836144d2565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b613e8681614560565b82525050565b6000613e9882846133a7565b915081905092915050565b6000602082019050613eb8600083018461337a565b92915050565b6000604082019050613ed3600083018561337a565b613ee06020830184613405565b9392505050565b6000604082019050613efc600083018561337a565b613f096020830184613e7d565b9392505050565b6000602082019050613f256000830184613389565b92915050565b6000602082019050613f406000830184613398565b92915050565b6000602082019050613f5b60008301846133d8565b92915050565b6000602082019050613f7660008301846133e7565b92915050565b6000602082019050613f9160008301846133f6565b92915050565b60006020820190508181036000830152613fb18184613414565b905092915050565b60006020820190508181036000830152613fd28161344d565b9050919050565b60006020820190508181036000830152613ff28161348d565b9050919050565b60006020820190508181036000830152614012816134cd565b9050919050565b6000602082019050818103600083015261403281613533565b9050919050565b6000602082019050818103600083015261405281613573565b9050919050565b60006020820190508181036000830152614072816135b3565b9050919050565b6000602082019050818103600083015261409281613619565b9050919050565b600060208201905081810360008301526140b281613659565b9050919050565b600060208201905081810360008301526140d281613699565b9050919050565b600060208201905081810360008301526140f2816136d9565b9050919050565b6000602082019050818103600083015261411281613719565b9050919050565b6000602082019050818103600083015261413281613759565b9050919050565b60006020820190508181036000830152614152816137bf565b9050919050565b60006020820190508181036000830152614172816137ff565b9050919050565b600060208201905081810360008301526141928161383f565b9050919050565b600060208201905081810360008301526141b28161387f565b9050919050565b600060208201905081810360008301526141d2816138bf565b9050919050565b600060208201905081810360008301526141f2816138ff565b9050919050565b600060208201905081810360008301526142128161393f565b9050919050565b60006020820190508181036000830152614232816139a5565b9050919050565b60006020820190508181036000830152614252816139e5565b9050919050565b6000602082019050818103600083015261427281613a4b565b9050919050565b6000602082019050818103600083015261429281613a8b565b9050919050565b600060208201905081810360008301526142b281613acb565b9050919050565b600060208201905081810360008301526142d281613b0b565b9050919050565b600060208201905081810360008301526142f281613b4b565b9050919050565b6000602082019050818103600083015261431281613bb1565b9050919050565b6000602082019050818103600083015261433281613bf1565b9050919050565b6000602082019050818103600083015261435281613c31565b9050919050565b6000602082019050818103600083015261437281613c71565b9050919050565b6000602082019050818103600083015261439281613cb1565b9050919050565b600060208201905081810360008301526143b281613d17565b9050919050565b600060208201905081810360008301526143d281613d7d565b9050919050565b600060208201905081810360008301526143f281613dbd565b9050919050565b6000602082019050818103600083015261441281613dfd565b9050919050565b6000602082019050818103600083015261443281613e3d565b9050919050565b600060208201905061444e6000830184613e7d565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561447b5761447a614609565b5b8060405250919050565b600067ffffffffffffffff8211156144a05761449f614609565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006144ee82614540565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061453b8261461c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006145758261457c565b9050919050565b600061458782614540565b9050919050565b6000614599826145a0565b9050919050565b60006145ab82614540565b9050919050565b60006145bd8261452d565b9050919050565b60006145cf82614560565b9050919050565b60005b838110156145f45780820151818401526020810190506145d9565b83811115614603576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061462d5761462c614609565b5b50565b614639816144e3565b811461464457600080fd5b50565b614650816144f5565b811461465b57600080fd5b50565b6003811061466b57600080fd5b50565b61467781614560565b811461468257600080fd5b5056fea264697066735822122013f3b022e354ddf49f7a28727f309f858a5cbdf70833a2e54da3c1a482b7073164736f6c63430007030033", + "deployedBytecode": "0x6080604052600436106102555760003560e01c806386d00e0211610139578063bc0163c1116100b6578063dc0706571161007a578063dc07065714610b93578063e8dda6f514610bbc578063e97d87d514610be7578063ebbab99214610c12578063f2fde38b14610c3d578063fc0c546a14610c6657610295565b8063bc0163c114610ac0578063bd896dcb14610aeb578063ce845d1d14610b14578063d0ebdbe714610b3f578063d18e81b314610b6857610295565b806391f7cfb9116100fd57806391f7cfb9146109ff578063a4caeb4214610a2a578063b0d1818c14610a55578063b470aade14610a7e578063b6549f7514610aa957610295565b806386d00e021461095057806386d1a69f1461097b578063872a7810146109925780638a5bdf5c146109bd5780638da5cb5b146109d457610295565b8063392e53cd116101d25780635051a5ec116101965780635051a5ec146108765780635b940081146108a157806360e79944146108cc578063715018a6146108e357806378e97925146108fa5780637bdf05af1461092557610295565b8063392e53cd1461079f578063398057a3146107ca57806344b1231f146107f557806345d30a1714610820578063481c6a751461084b57610295565b80632a627814116102195780632a627814146106dc5780632bc9ed02146106f35780633197cbb61461071e57806337aeb0861461074957806338af3eed1461077457610295565b8063029c6c9f1461061957806306040618146106445780630b80f7771461066f5780630dff24d5146106865780630fb5a6b4146106b157610295565b36610295576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161028c90613fb9565b60405180910390fd5b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610325576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161031c90614199565b60405180910390fd5b60003414610368576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161035f90613fd9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663f1d24c456000357fffffffff00000000000000000000000000000000000000000000000000000000166040518263ffffffff1660e01b81526004016103e99190613f2b565b60206040518083038186803b15801561040157600080fd5b505afa158015610415573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061043991906131a5565b9050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156104ab576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104a290614299565b60405180910390fd5b60006104b5610c91565b9050610506826000368080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610d43565b506001600281111561051457fe5b603b60009054906101000a900460ff16600281111561052f57fe5b141561061557600061053f610c91565b90508181101561058157600061055e8284610d8d90919063ffffffff16565b905061057581603f54610ddd90919063ffffffff16565b603f81905550506105c7565b60006105968383610d8d90919063ffffffff16565b9050603f548110156105bc576105b781603f54610d8d90919063ffffffff16565b6105bf565b60005b603f81905550505b6105cf610e32565b603f541115610613576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060a906141f9565b60405180910390fd5b505b5050005b34801561062557600080fd5b5061062e610ea1565b60405161063b9190614439565b60405180910390f35b34801561065057600080fd5b50610659610ebf565b6040516106669190614439565b60405180910390f35b34801561067b57600080fd5b50610684610efa565b005b34801561069257600080fd5b5061069b611067565b6040516106a89190614439565b60405180910390f35b3480156106bd57600080fd5b506106c66110ae565b6040516106d39190614439565b60405180910390f35b3480156106e857600080fd5b506106f16110cc565b005b3480156106ff57600080fd5b50610708611331565b6040516107159190613f10565b60405180910390f35b34801561072a57600080fd5b50610733611344565b6040516107409190614439565b60405180910390f35b34801561075557600080fd5b5061075e61134a565b60405161076b9190614439565b60405180910390f35b34801561078057600080fd5b50610789611350565b6040516107969190613ea3565b60405180910390f35b3480156107ab57600080fd5b506107b4611376565b6040516107c19190613f10565b60405180910390f35b3480156107d657600080fd5b506107df611389565b6040516107ec9190614439565b60405180910390f35b34801561080157600080fd5b5061080a610e32565b6040516108179190614439565b60405180910390f35b34801561082c57600080fd5b5061083561138f565b6040516108429190614439565b60405180910390f35b34801561085757600080fd5b50610860611395565b60405161086d9190613f61565b60405180910390f35b34801561088257600080fd5b5061088b6113bb565b6040516108989190613f10565b60405180910390f35b3480156108ad57600080fd5b506108b66113ce565b6040516108c39190614439565b60405180910390f35b3480156108d857600080fd5b506108e16114d9565b005b3480156108ef57600080fd5b506108f861171f565b005b34801561090657600080fd5b5061090f61186b565b60405161091c9190614439565b60405180910390f35b34801561093157600080fd5b5061093a611871565b6040516109479190614439565b60405180910390f35b34801561095c57600080fd5b506109656118ad565b6040516109729190614439565b60405180910390f35b34801561098757600080fd5b506109906118b3565b005b34801561099e57600080fd5b506109a7611a8f565b6040516109b49190613f7c565b60405180910390f35b3480156109c957600080fd5b506109d2611aa2565b005b3480156109e057600080fd5b506109e9611b7b565b6040516109f69190613ea3565b60405180910390f35b348015610a0b57600080fd5b50610a14611ba4565b604051610a219190614439565b60405180910390f35b348015610a3657600080fd5b50610a3f611c02565b604051610a4c9190614439565b60405180910390f35b348015610a6157600080fd5b50610a7c6004803603810190610a779190613328565b611c08565b005b348015610a8a57600080fd5b50610a93611e07565b604051610aa09190614439565b60405180910390f35b348015610ab557600080fd5b50610abe611e2a565b005b348015610acc57600080fd5b50610ad56120c2565b604051610ae29190614439565b60405180910390f35b348015610af757600080fd5b50610b126004803603810190610b0d91906131ce565b6120f4565b005b348015610b2057600080fd5b50610b29610c91565b604051610b369190614439565b60405180910390f35b348015610b4b57600080fd5b50610b666004803603810190610b61919061317c565b61211c565b005b348015610b7457600080fd5b50610b7d6121b6565b604051610b8a9190614439565b60405180910390f35b348015610b9f57600080fd5b50610bba6004803603810190610bb5919061317c565b6121be565b005b348015610bc857600080fd5b50610bd1612339565b604051610bde9190614439565b60405180910390f35b348015610bf357600080fd5b50610bfc61233f565b604051610c099190614439565b60405180910390f35b348015610c1e57600080fd5b50610c27612345565b604051610c349190614439565b60405180910390f35b348015610c4957600080fd5b50610c646004803603810190610c5f919061317c565b612367565b005b348015610c7257600080fd5b50610c7b612522565b604051610c889190613f46565b60405180910390f35b6000603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cee9190613ea3565b60206040518083038186803b158015610d0657600080fd5b505afa158015610d1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3e9190613351565b905090565b6060610d8583836040518060400160405280601e81526020017f416464726573733a206c6f772d6c6576656c2063616c6c206661696c65640000815250612548565b905092915050565b600082821115610dd2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dc9906140f9565b60405180910390fd5b818303905092915050565b600080828401905083811015610e28576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e1f90614079565b60405180910390fd5b8091505092915050565b6000600280811115610e4057fe5b603b60009054906101000a900460ff166002811115610e5b57fe5b1415610e6b576035549050610e9e565b6000603a54118015610e855750603a54610e836121b6565b105b15610e935760009050610e9e565b610e9b611ba4565b90505b90565b6000610eba60385460355461256090919063ffffffff16565b905090565b6000610ef56001610ee7610ed1611e07565b610ed9611871565b61256090919063ffffffff16565b610ddd90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610f88576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f7f90614259565b60405180910390fd5b60001515603b60039054906101000a900460ff16151514610fde576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610fd5906140d9565b60405180910390fd5b611039610fe9611b7b565b610ff1610c91565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b7f171f0bcbda3370351cea17f3b164bee87d77c2503b94abdf2720a814ebe7e9df60405160405180910390a1565b600080611072610c91565b9050600061107e6120c2565b9050808211156110a45761109b8183610d8d90919063ffffffff16565b925050506110ab565b6000925050505b90565b60006110c7603654603754610d8d90919063ffffffff16565b905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461115c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161115390614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156111c657600080fd5b505afa1580156111da573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061120391906132be565b905060005b815181101561130157603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061125b57fe5b60200260200101517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040518363ffffffff1660e01b81526004016112a1929190613ee7565b602060405180830381600087803b1580156112bb57600080fd5b505af11580156112cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112f391906132ff565b508080600101915050611208565b507fb837fd51506ba3cc623a37c78ed22fd521f2f6e9f69a34d5c2a4a9474f27579360405160405180910390a150565b603b60019054906101000a900460ff1681565b60375481565b603d5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60029054906101000a900460ff1681565b60355481565b603c5481565b603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b603b60039054906101000a900460ff1681565b60006002808111156113dc57fe5b603b60009054906101000a900460ff1660028111156113f757fe5b141561140c5761140561263c565b90506114d6565b600060395411801561142657506039546114246121b6565b105b1561143457600090506114d6565b6001600281111561144157fe5b603b60009054906101000a900460ff16600281111561145c57fe5b14801561146b57506000603a54115b801561147f5750603a5461147d6121b6565b105b1561148d57600090506114d6565b60006114bf603f546114b1603c546114a3611ba4565b610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b90506114d26114cc610c91565b826126f6565b9150505b90565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611569576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161156090614359565b60405180910390fd5b6060603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a34574666040518163ffffffff1660e01b815260040160006040518083038186803b1580156115d357600080fd5b505afa1580156115e7573d6000803e3d6000fd5b505050506040513d6000823e3d601f19601f8201168201806040525081019061161091906132be565b905060005b81518110156116ef57603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663095ea7b383838151811061166857fe5b602002602001015160006040518363ffffffff1660e01b815260040161168f929190613ebe565b602060405180830381600087803b1580156116a957600080fd5b505af11580156116bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e191906132ff565b508080600101915050611615565b507f6d317a20ba9d790014284bef285283cd61fde92e0f2711050f563a9d2cf4171160405160405180910390a150565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146117ad576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a490614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60365481565b60008061187c6121b6565b905060365481116118915760009150506118aa565b6118a660365482610d8d90919063ffffffff16565b9150505b90565b603a5481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611943576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161193a90614359565b60405180910390fd5b600061194d6113ce565b905060008111611992576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611989906143b9565b60405180910390fd5b6119a781603c54610ddd90919063ffffffff16565b603c81905550611a1c603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df9317982604051611a849190614439565b60405180910390a250565b603b60009054906101000a900460ff1681565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611b32576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b2990614359565b60405180910390fd5b6001603b60036101000a81548160ff0219169083151502179055507fbeb3313724453131feb0a765a03e6715bb720e0f973a31fcbafa2d2f048c188b60405160405180910390a1565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600080611baf6121b6565b9050603654811015611bc5576000915050611bff565b603754811115611bda57603554915050611bff565b611bfb611be5610ea1565b611bed612345565b61270f90919063ffffffff16565b9150505b90565b60385481565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614611c98576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c8f90614359565b60405180910390fd5b60008111611cdb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd2906141d9565b60405180910390fd5b80611ce4611067565b1015611d25576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d1c906142d9565b60405180910390fd5b611d94603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f6352c5382c4a4578e712449ca65e83cdb392d045dfcf1cad9615189db2da244b82604051611dfc9190614439565b60405180910390a250565b6000611e25603854611e176110ae565b61256090919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611eb8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611eaf90614259565b60405180910390fd5b60016002811115611ec557fe5b603b60009054906101000a900460ff166002811115611ee057fe5b14611f20576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f1790614319565b60405180910390fd5b60001515603b60019054906101000a900460ff16151514611f76576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f6d90614419565b60405180910390fd5b6000611f94611f83610e32565b603554610d8d90919063ffffffff16565b905060008111611fd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fd090614099565b60405180910390fd5b80603d819055506001603b60016101000a81548160ff02191690831515021790555061204f612006611b7b565b82603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166125b69092919063ffffffff16565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fb73c49a3a37a7aca291ba0ceaa41657012def406106a7fc386888f0f66e941cf826040516120b79190614439565b60405180910390a250565b60006120ef603d546120e1603c54603554610d8d90919063ffffffff16565b610d8d90919063ffffffff16565b905090565b6121068a8a8a8a8a8a8a8a8a8a61277f565b61210f8b612c09565b5050505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146121aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121a190614259565b60405180910390fd5b6121b381612c09565b50565b600042905090565b603460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461224e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161224590614359565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156122be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122b590614179565b60405180910390fd5b80603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507f373c72efabe4ef3e552ff77838be729f3bc3d8c586df0012902d1baa2377fa1d8160405161232e9190613ea3565b60405180910390a150565b603f5481565b60395481565b60006123626001612354610ebf565b610d8d90919063ffffffff16565b905090565b3373ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146123f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123ec90614259565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161245c90614059565b60405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1660008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b603360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60606125578484600085612d87565b90509392505050565b60008082116125a4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161259b90614159565b60405180910390fd5b8183816125ad57fe5b04905092915050565b6126378363a9059cbb60e01b84846040516024016125d5929190613ee7565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612e9c565b505050565b60008060395411801561265757506039546126556121b6565b105b1561266557600090506126f3565b6001600281111561267257fe5b603b60009054906101000a900460ff16600281111561268d57fe5b14801561269c57506000603a54115b80156126b05750603a546126ae6121b6565b105b156126be57600090506126f3565b60006126dc603c546126ce611ba4565b610d8d90919063ffffffff16565b90506126ef6126e9610c91565b826126f6565b9150505b90565b60008183106127055781612707565b825b905092915050565b6000808314156127225760009050612779565b600082840290508284828161273357fe5b0414612774576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161276b90614239565b60405180910390fd5b809150505b92915050565b603b60029054906101000a900460ff16156127cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127c6906142f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168a73ffffffffffffffffffffffffffffffffffffffff16141561283f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612836906140b9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614156128af576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128a6906143f9565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff16141561291f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612916906143d9565b60405180910390fd5b60008711612962576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161295990614139565b60405180910390fd5b60008614156129a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161299d90614279565b60405180910390fd5b8486106129e8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129df90614019565b60405180910390fd5b6001841015612a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a2390614219565b60405180910390fd5b60006002811115612a3957fe5b816002811115612a4557fe5b1415612a86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a7d90614039565b60405180910390fd5b848310612ac8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612abf90614379565b60405180910390fd5b848210612b0a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b0190613ff9565b60405180910390fd5b6001603b60026101000a81548160ff021916908315150217905550612b2e8a612f63565b88603460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555087603360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550866035819055508560368190555084603781905550836038819055508260398190555081603a8190555080603b60006101000a81548160ff02191690836002811115612bf857fe5b021790555050505050505050505050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415612c79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c7090614339565b60405180910390fd5b612c8281613001565b612cc1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb8906141b9565b60405180910390fd5b6000603e60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905081603e60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167fdac3632743b879638fd2d51c4d3c1dd796615b4758a55b50b0c19b971ba9fbc760405160405180910390a35050565b606082471015612dcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612dc390614119565b60405180910390fd5b612dd585613001565b612e14576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e0b906142b9565b60405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff168587604051612e3e9190613e8c565b60006040518083038185875af1925050503d8060008114612e7b576040519150601f19603f3d011682016040523d82523d6000602084013e612e80565b606091505b5091509150612e90828286613014565b92505050949350505050565b6060612efe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125489092919063ffffffff16565b9050600081511115612f5e5780806020019051810190612f1e91906132ff565b612f5d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5490614399565b60405180910390fd5b5b505050565b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350565b600080823b905060008111915050919050565b6060831561302457829050613074565b6000835111156130375782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161306b9190613f97565b60405180910390fd5b9392505050565b60008135905061308a81614630565b92915050565b60008151905061309f81614630565b92915050565b600082601f8301126130b657600080fd5b81516130c96130c482614485565b614454565b915081818352602084019350602081019050838560208402820111156130ee57600080fd5b60005b8381101561311e57816131048882613090565b8452602084019350602083019250506001810190506130f1565b5050505092915050565b60008151905061313781614647565b92915050565b60008135905061314c8161465e565b92915050565b6000813590506131618161466e565b92915050565b6000815190506131768161466e565b92915050565b60006020828403121561318e57600080fd5b600061319c8482850161307b565b91505092915050565b6000602082840312156131b757600080fd5b60006131c584828501613090565b91505092915050565b60008060008060008060008060008060006101608c8e0312156131f057600080fd5b60006131fe8e828f0161307b565b9b5050602061320f8e828f0161307b565b9a505060406132208e828f0161307b565b99505060606132318e828f0161307b565b98505060806132428e828f01613152565b97505060a06132538e828f01613152565b96505060c06132648e828f01613152565b95505060e06132758e828f01613152565b9450506101006132878e828f01613152565b9350506101206132998e828f01613152565b9250506101406132ab8e828f0161313d565b9150509295989b509295989b9093969950565b6000602082840312156132d057600080fd5b600082015167ffffffffffffffff8111156132ea57600080fd5b6132f6848285016130a5565b91505092915050565b60006020828403121561331157600080fd5b600061331f84828501613128565b91505092915050565b60006020828403121561333a57600080fd5b600061334884828501613152565b91505092915050565b60006020828403121561336357600080fd5b600061337184828501613167565b91505092915050565b613383816144e3565b82525050565b613392816144f5565b82525050565b6133a181614501565b82525050565b60006133b2826144b1565b6133bc81856144c7565b93506133cc8185602086016145d6565b80840191505092915050565b6133e18161456a565b82525050565b6133f08161458e565b82525050565b6133ff816145b2565b82525050565b61340e816145c4565b82525050565b600061341f826144bc565b61342981856144d2565b93506134398185602086016145d6565b6134428161460b565b840191505092915050565b600061345a6008836144d2565b91507f4261642063616c6c0000000000000000000000000000000000000000000000006000830152602082019050919050565b600061349a601b836144d2565b91507f455448207472616e7366657273206e6f7420737570706f7274656400000000006000830152602082019050919050565b60006134da6022836144d2565b91507f436c6966662074696d65206d757374206265206265666f726520656e6420746960008301527f6d650000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006135406015836144d2565b91507f53746172742074696d65203e20656e642074696d6500000000000000000000006000830152602082019050919050565b6000613580601e836144d2565b91507f4d757374207365742061207265766f636162696c697479206f7074696f6e00006000830152602082019050919050565b60006135c06026836144d2565b91507f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008301527f64647265737300000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613626601b836144d2565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000613666601c836144d2565b91507f4e6f20617661696c61626c6520756e76657374656420616d6f756e74000000006000830152602082019050919050565b60006136a66014836144d2565b91507f4f776e65722063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b60006136e6601f836144d2565b91507f43616e6e6f742063616e63656c20616363657074656420636f6e7472616374006000830152602082019050919050565b6000613726601e836144d2565b91507f536166654d6174683a207375627472616374696f6e206f766572666c6f7700006000830152602082019050919050565b60006137666026836144d2565b91507f416464726573733a20696e73756666696369656e742062616c616e636520666f60008301527f722063616c6c00000000000000000000000000000000000000000000000000006020830152604082019050919050565b60006137cc601d836144d2565b91507f4d616e6167656420746f6b656e732063616e6e6f74206265207a65726f0000006000830152602082019050919050565b600061380c601a836144d2565b91507f536166654d6174683a206469766973696f6e206279207a65726f0000000000006000830152602082019050919050565b600061384c6011836144d2565b91507f456d7074792062656e65666963696172790000000000000000000000000000006000830152602082019050919050565b600061388c6013836144d2565b91507f556e617574686f72697a65642063616c6c6572000000000000000000000000006000830152602082019050919050565b60006138cc601a836144d2565b91507f4d616e61676572206d757374206265206120636f6e74726163740000000000006000830152602082019050919050565b600061390c6015836144d2565b91507f416d6f756e742063616e6e6f74206265207a65726f00000000000000000000006000830152602082019050919050565b600061394c6029836144d2565b91507f43616e6e6f7420757365206d6f726520746f6b656e73207468616e207665737460008301527f656420616d6f756e7400000000000000000000000000000000000000000000006020830152604082019050919050565b60006139b2601f836144d2565b91507f506572696f64732063616e6e6f742062652062656c6f77206d696e696d756d006000830152602082019050919050565b60006139f26021836144d2565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613a586020836144d2565b91507f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726000830152602082019050919050565b6000613a986016836144d2565b91507f53746172742074696d65206d75737420626520736574000000000000000000006000830152602082019050919050565b6000613ad86015836144d2565b91507f556e617574686f72697a65642066756e6374696f6e00000000000000000000006000830152602082019050919050565b6000613b18601d836144d2565b91507f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006000830152602082019050919050565b6000613b586024836144d2565b91507f416d6f756e7420726571756573746564203e20737572706c757320617661696c60008301527f61626c65000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613bbe6013836144d2565b91507f416c726561647920696e697469616c697a6564000000000000000000000000006000830152602082019050919050565b6000613bfe6019836144d2565b91507f436f6e7472616374206973206e6f6e2d7265766f6361626c65000000000000006000830152602082019050919050565b6000613c3e6017836144d2565b91507f4d616e616765722063616e6e6f7420626520656d7074790000000000000000006000830152602082019050919050565b6000613c7e6005836144d2565b91507f21617574680000000000000000000000000000000000000000000000000000006000830152602082019050919050565b6000613cbe602a836144d2565b91507f52656c656173652073746172742074696d65206d757374206265206265666f7260008301527f6520656e642074696d65000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d24602a836144d2565b91507f5361666545524332303a204552433230206f7065726174696f6e20646964206e60008301527f6f742073756363656564000000000000000000000000000000000000000000006020830152604082019050919050565b6000613d8a601e836144d2565b91507f4e6f20617661696c61626c652072656c65617361626c6520616d6f756e7400006000830152602082019050919050565b6000613dca6014836144d2565b91507f546f6b656e2063616e6e6f74206265207a65726f0000000000000000000000006000830152602082019050919050565b6000613e0a601a836144d2565b91507f42656e65666963696172792063616e6e6f74206265207a65726f0000000000006000830152602082019050919050565b6000613e4a600f836144d2565b91507f416c7265616479207265766f6b656400000000000000000000000000000000006000830152602082019050919050565b613e8681614560565b82525050565b6000613e9882846133a7565b915081905092915050565b6000602082019050613eb8600083018461337a565b92915050565b6000604082019050613ed3600083018561337a565b613ee06020830184613405565b9392505050565b6000604082019050613efc600083018561337a565b613f096020830184613e7d565b9392505050565b6000602082019050613f256000830184613389565b92915050565b6000602082019050613f406000830184613398565b92915050565b6000602082019050613f5b60008301846133d8565b92915050565b6000602082019050613f7660008301846133e7565b92915050565b6000602082019050613f9160008301846133f6565b92915050565b60006020820190508181036000830152613fb18184613414565b905092915050565b60006020820190508181036000830152613fd28161344d565b9050919050565b60006020820190508181036000830152613ff28161348d565b9050919050565b60006020820190508181036000830152614012816134cd565b9050919050565b6000602082019050818103600083015261403281613533565b9050919050565b6000602082019050818103600083015261405281613573565b9050919050565b60006020820190508181036000830152614072816135b3565b9050919050565b6000602082019050818103600083015261409281613619565b9050919050565b600060208201905081810360008301526140b281613659565b9050919050565b600060208201905081810360008301526140d281613699565b9050919050565b600060208201905081810360008301526140f2816136d9565b9050919050565b6000602082019050818103600083015261411281613719565b9050919050565b6000602082019050818103600083015261413281613759565b9050919050565b60006020820190508181036000830152614152816137bf565b9050919050565b60006020820190508181036000830152614172816137ff565b9050919050565b600060208201905081810360008301526141928161383f565b9050919050565b600060208201905081810360008301526141b28161387f565b9050919050565b600060208201905081810360008301526141d2816138bf565b9050919050565b600060208201905081810360008301526141f2816138ff565b9050919050565b600060208201905081810360008301526142128161393f565b9050919050565b60006020820190508181036000830152614232816139a5565b9050919050565b60006020820190508181036000830152614252816139e5565b9050919050565b6000602082019050818103600083015261427281613a4b565b9050919050565b6000602082019050818103600083015261429281613a8b565b9050919050565b600060208201905081810360008301526142b281613acb565b9050919050565b600060208201905081810360008301526142d281613b0b565b9050919050565b600060208201905081810360008301526142f281613b4b565b9050919050565b6000602082019050818103600083015261431281613bb1565b9050919050565b6000602082019050818103600083015261433281613bf1565b9050919050565b6000602082019050818103600083015261435281613c31565b9050919050565b6000602082019050818103600083015261437281613c71565b9050919050565b6000602082019050818103600083015261439281613cb1565b9050919050565b600060208201905081810360008301526143b281613d17565b9050919050565b600060208201905081810360008301526143d281613d7d565b9050919050565b600060208201905081810360008301526143f281613dbd565b9050919050565b6000602082019050818103600083015261441281613dfd565b9050919050565b6000602082019050818103600083015261443281613e3d565b9050919050565b600060208201905061444e6000830184613e7d565b92915050565b6000604051905081810181811067ffffffffffffffff8211171561447b5761447a614609565b5b8060405250919050565b600067ffffffffffffffff8211156144a05761449f614609565b5b602082029050602081019050919050565b600081519050919050565b600081519050919050565b600081905092915050565b600082825260208201905092915050565b60006144ee82614540565b9050919050565b60008115159050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600081905061453b8261461c565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b60006145758261457c565b9050919050565b600061458782614540565b9050919050565b6000614599826145a0565b9050919050565b60006145ab82614540565b9050919050565b60006145bd8261452d565b9050919050565b60006145cf82614560565b9050919050565b60005b838110156145f45780820151818401526020810190506145d9565b83811115614603576000848401525b50505050565bfe5b6000601f19601f8301169050919050565b6003811061462d5761462c614609565b5b50565b614639816144e3565b811461464457600080fd5b50565b614650816144f5565b811461465b57600080fd5b50565b6003811061466b57600080fd5b50565b61467781614560565b811461468257600080fd5b5056fea264697066735822122013f3b022e354ddf49f7a28727f309f858a5cbdf70833a2e54da3c1a482b7073164736f6c63430007030033", + "devdoc": { + "kind": "dev", + "methods": { + "acceptLock()": { + "details": "Can only be called by the beneficiary" + }, + "amountPerPeriod()": { + "returns": { + "_0": "Amount of tokens available after each period" + } + }, + "approveProtocol()": { + "details": "Approves all token destinations registered in the manager to pull tokens" + }, + "availableAmount()": { + "details": "Implements the step-by-step schedule based on periods for available tokens", + "returns": { + "_0": "Amount of tokens available according to the schedule" + } + }, + "cancelLock()": { + "details": "Can only be called by the owner" + }, + "changeBeneficiary(address)": { + "details": "Can only be called by the beneficiary", + "params": { + "_newBeneficiary": "Address of the new beneficiary address" + } + }, + "currentBalance()": { + "returns": { + "_0": "Tokens held in the contract" + } + }, + "currentPeriod()": { + "returns": { + "_0": "A number that represents the current period" + } + }, + "currentTime()": { + "returns": { + "_0": "Current block timestamp" + } + }, + "duration()": { + "returns": { + "_0": "Amount of seconds from contract startTime to endTime" + } + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "passedPeriods()": { + "returns": { + "_0": "A number of periods that passed since the schedule started" + } + }, + "periodDuration()": { + "returns": { + "_0": "Duration of each period in seconds" + } + }, + "releasableAmount()": { + "details": "Considers the schedule, takes into account already released tokens and used amount", + "returns": { + "_0": "Amount of tokens ready to be released" + } + }, + "release()": { + "details": "All available releasable tokens are transferred to beneficiary" + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "revoke()": { + "details": "Vesting schedule is always calculated based on managed tokens" + }, + "revokeProtocol()": { + "details": "Revokes approval to all token destinations in the manager to pull tokens" + }, + "setManager(address)": { + "params": { + "_newManager": "Address of the new manager" + } + }, + "sinceStartTime()": { + "details": "Returns zero if called before conctract starTime", + "returns": { + "_0": "Seconds elapsed from contract startTime" + } + }, + "surplusAmount()": { + "details": "All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary. Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be skewed, so the beneficiary might have to bridge back to L1 to release the surplus.", + "returns": { + "_0": "Amount of tokens considered as surplus" + } + }, + "totalOutstandingAmount()": { + "details": "Does not consider schedule but just global amounts tracked", + "returns": { + "_0": "Amount of outstanding tokens for the lifetime of the contract" + } + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + }, + "vestedAmount()": { + "details": "Similar to available amount, but is fully vested when contract is non-revocable", + "returns": { + "_0": "Amount of tokens already vested" + } + }, + "withdrawSurplus(uint256)": { + "details": "Tokens in the contract over outstanding amount are considered as surplus", + "params": { + "_amount": "Amount of tokens to withdraw" + } + } + }, + "title": "GraphTokenLockWallet", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "acceptLock()": { + "notice": "Beneficiary accepts the lock, the owner cannot retrieve back the tokens" + }, + "amountPerPeriod()": { + "notice": "Returns amount available to be released after each period according to schedule" + }, + "approveProtocol()": { + "notice": "Approves protocol access of the tokens managed by this contract" + }, + "availableAmount()": { + "notice": "Gets the currently available token according to the schedule" + }, + "cancelLock()": { + "notice": "Owner cancel the lock and return the balance in the contract" + }, + "changeBeneficiary(address)": { + "notice": "Change the beneficiary of funds managed by the contract" + }, + "currentBalance()": { + "notice": "Returns the amount of tokens currently held by the contract" + }, + "currentPeriod()": { + "notice": "Gets the current period based on the schedule" + }, + "currentTime()": { + "notice": "Returns the current block timestamp" + }, + "duration()": { + "notice": "Gets duration of contract from start to end in seconds" + }, + "passedPeriods()": { + "notice": "Gets the number of periods that passed since the first period" + }, + "periodDuration()": { + "notice": "Returns the duration of each period in seconds" + }, + "releasableAmount()": { + "notice": "Gets tokens currently available for release" + }, + "release()": { + "notice": "Releases tokens based on the configured schedule" + }, + "revoke()": { + "notice": "Revokes a vesting schedule and return the unvested tokens to the owner" + }, + "revokeProtocol()": { + "notice": "Revokes protocol access of the tokens managed by this contract" + }, + "setManager(address)": { + "notice": "Sets a new manager for this contract" + }, + "sinceStartTime()": { + "notice": "Gets time elapsed since the start of the contract" + }, + "surplusAmount()": { + "notice": "Gets surplus amount in the contract based on outstanding amount to release" + }, + "totalOutstandingAmount()": { + "notice": "Gets the outstanding amount yet to be released based on the whole contract lifetime" + }, + "vestedAmount()": { + "notice": "Gets the amount of currently vested tokens" + }, + "withdrawSurplus(uint256)": { + "notice": "Withdraws surplus, unmanaged tokens from the contract" + } + }, + "notice": "This contract is built on top of the base GraphTokenLock functionality. It allows wallet beneficiaries to use the deposited funds to perform specific function calls on specific contracts. The idea is that supporters with locked tokens can participate in the protocol but disallow any release before the vesting/lock schedule. The beneficiary can issue authorized function calls to this contract that will get forwarded to a target contract. A target contract is any of our protocol contracts. The function calls allowed are queried to the GraphTokenLockManager, this way the same configuration can be shared for all the created lock wallet contracts. NOTE: Contracts used as target must have its function signatures checked to avoid collisions with any of this contract functions. Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience the maximum amount of tokens is authorized. Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 6817, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "_owner", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 6822, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 3244, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "token", + "offset": 0, + "slot": "51", + "type": "t_contract(IERC20)1710" + }, + { + "astId": 3246, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "beneficiary", + "offset": 0, + "slot": "52", + "type": "t_address" + }, + { + "astId": 3248, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "managedAmount", + "offset": 0, + "slot": "53", + "type": "t_uint256" + }, + { + "astId": 3250, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "startTime", + "offset": 0, + "slot": "54", + "type": "t_uint256" + }, + { + "astId": 3252, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "endTime", + "offset": 0, + "slot": "55", + "type": "t_uint256" + }, + { + "astId": 3254, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "periods", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 3256, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releaseStartTime", + "offset": 0, + "slot": "57", + "type": "t_uint256" + }, + { + "astId": 3258, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "vestingCliffTime", + "offset": 0, + "slot": "58", + "type": "t_uint256" + }, + { + "astId": 3260, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revocable", + "offset": 0, + "slot": "59", + "type": "t_enum(Revocability)5096" + }, + { + "astId": 3262, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isRevoked", + "offset": 1, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3264, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isInitialized", + "offset": 2, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3266, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "isAccepted", + "offset": 3, + "slot": "59", + "type": "t_bool" + }, + { + "astId": 3268, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "releasedAmount", + "offset": 0, + "slot": "60", + "type": "t_uint256" + }, + { + "astId": 3270, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "revokedAmount", + "offset": 0, + "slot": "61", + "type": "t_uint256" + }, + { + "astId": 4692, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "manager", + "offset": 0, + "slot": "62", + "type": "t_contract(IGraphTokenLockManager)5278" + }, + { + "astId": 4694, + "contract": "contracts/GraphTokenLockWallet.sol:GraphTokenLockWallet", + "label": "usedAmount", + "offset": 0, + "slot": "63", + "type": "t_uint256" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(IERC20)1710": { + "encoding": "inplace", + "label": "contract IERC20", + "numberOfBytes": "20" + }, + "t_contract(IGraphTokenLockManager)5278": { + "encoding": "inplace", + "label": "contract IGraphTokenLockManager", + "numberOfBytes": "20" + }, + "t_enum(Revocability)5096": { + "encoding": "inplace", + "label": "enum IGraphTokenLock.Revocability", + "numberOfBytes": "1" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/sepolia/L1GraphTokenLockTransferTool.json b/packages/token-distribution/deployments/sepolia/L1GraphTokenLockTransferTool.json new file mode 100644 index 000000000..458bd5585 --- /dev/null +++ b/packages/token-distribution/deployments/sepolia/L1GraphTokenLockTransferTool.json @@ -0,0 +1,636 @@ +{ + "address": "0x543F8BFFb65c46091B4eEF4b1c394dFa43C4b065", + "abi": [ + { + "inputs": [ + { + "internalType": "contract IERC20", + "name": "_graphToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2Implementation", + "type": "address" + }, + { + "internalType": "contract ITokenGateway", + "name": "_l1Gateway", + "type": "address" + }, + { + "internalType": "address payable", + "name": "_staking", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHPulled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "tokenLock", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "destination", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ETHWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Beneficiary", + "type": "address" + } + ], + "name": "L2BeneficiarySet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1LockManager", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + } + ], + "name": "L2LockManagerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + } + ], + "name": "L2WalletAddressSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1WalletOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2WalletOwner", + "type": "address" + } + ], + "name": "L2WalletOwnerSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "l1Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l2Wallet", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "l1LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "l2LockManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "LockedFundsSentToL2", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "proxy", + "type": "address" + } + ], + "name": "ProxyCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenLock", + "type": "address" + } + ], + "name": "depositETH", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "address", + "name": "_l2Beneficiary", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxGas", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_gasPriceBid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_maxSubmissionCost", + "type": "uint256" + } + ], + "name": "depositToL2Locked", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + }, + { + "internalType": "address", + "name": "_deployer", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_salt", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "_implementation", + "type": "address" + } + ], + "name": "getDeploymentAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "graphToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "l1Gateway", + "outputs": [ + { + "internalType": "contract ITokenGateway", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2Beneficiary", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "l2Implementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2LockManager", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletAddressSetManually", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "l2WalletOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_tokenLock", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "pullETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1LockManager", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2LockManager", + "type": "address" + } + ], + "name": "setL2LockManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l2Wallet", + "type": "address" + } + ], + "name": "setL2WalletAddressManually", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_l1WalletOwner", + "type": "address" + }, + { + "internalType": "address", + "name": "_l2WalletOwner", + "type": "address" + } + ], + "name": "setL2WalletOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "staking", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenLockETHBalances", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_destination", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdrawETH", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x73d09cc6f92b3c97de26d3049db72a41249e0772d45c24c3818bce3344de8070" +} \ No newline at end of file diff --git a/packages/token-distribution/deployments/sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json b/packages/token-distribution/deployments/sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json new file mode 100644 index 000000000..e7a4b87c0 --- /dev/null +++ b/packages/token-distribution/deployments/sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json @@ -0,0 +1,152 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMathUpgradeable {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\n// solhint-disable-next-line compiler-version\npragma solidity >=0.4.24 <0.8.0;\n\nimport \"../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(_initializing || _isConstructor() || !_initialized, \"Initializable: contract is already initialized\");\n\n bool isTopLevelCall = !_initializing;\n if (isTopLevelCall) {\n _initializing = true;\n _initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n _initializing = false;\n }\n }\n\n /// @dev Returns true if and only if the function is running in the constructor\n function _isConstructor() private view returns (bool) {\n return !AddressUpgradeable.isContract(address(this));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../utils/Context.sol\";\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor () internal {\n address msgSender = _msgSender();\n _owner = msgSender;\n emit OwnershipTransferred(address(0), msgSender);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\n mapping (address => uint256) private _balances;\n\n mapping (address => mapping (address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5,05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is\n * called.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return _decimals;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be to transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.sol\";\nimport \"../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require((value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\n (bool success, ) = recipient.call{ value: amount }(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain`call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.call{ value: value }(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.staticcall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/*\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with GSN meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Create2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.\n * `CREATE2` can be used to compute in advance the address where a smart\n * contract will be deployed, which allows for interesting new mechanisms known\n * as 'counterfactual interactions'.\n *\n * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more\n * information.\n */\nlibrary Create2 {\n /**\n * @dev Deploys a contract using `CREATE2`. The address where the contract\n * will be deployed can be known in advance via {computeAddress}.\n *\n * The bytecode for a contract can be obtained from Solidity with\n * `type(contractName).creationCode`.\n *\n * Requirements:\n *\n * - `bytecode` must not be empty.\n * - `salt` must have not been used for `bytecode` already.\n * - the factory must have a balance of at least `amount`.\n * - if `amount` is non-zero, `bytecode` must have a `payable` constructor.\n */\n function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address) {\n address addr;\n require(address(this).balance >= amount, \"Create2: insufficient balance\");\n require(bytecode.length != 0, \"Create2: bytecode length is zero\");\n // solhint-disable-next-line no-inline-assembly\n assembly {\n addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)\n }\n require(addr != address(0), \"Create2: Failed on deploy\");\n return addr;\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the\n * `bytecodeHash` or `salt` will result in a new destination address.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {\n return computeAddress(salt, bytecodeHash, address(this));\n }\n\n /**\n * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at\n * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}.\n */\n function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address) {\n bytes32 _data = keccak256(\n abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHash)\n );\n return address(uint160(uint256(_data)));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping (bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) { // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n bytes32 lastvalue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastvalue;\n // Update the index for the moved value\n set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n return set._values[index];\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n}\n" + }, + "contracts/arbitrum/ITokenGateway.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2020, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-peripherals\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.6 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\ninterface ITokenGateway {\n /// @notice event deprecated in favor of DepositInitiated and WithdrawalInitiated\n // event OutboundTransferInitiated(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n /// @notice event deprecated in favor of DepositFinalized and WithdrawalFinalized\n // event InboundTransferFinalized(\n // address token,\n // address indexed _from,\n // address indexed _to,\n // uint256 indexed _transferId,\n // uint256 _amount,\n // bytes _data\n // );\n\n function outboundTransfer(\n address _token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory);\n\n function finalizeInboundTransfer(\n address _token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable;\n\n /**\n * @notice Calculate the address used when bridging an ERC20 token\n * @dev the L1 and L2 address oracles may not always be in sync.\n * For example, a custom token may have been registered but not deployed or the contract self destructed.\n * @param l1ERC20 address of L1 token\n * @return L2 address of a bridged ERC20 token\n */\n function calculateL2TokenAddress(address l1ERC20) external view returns (address);\n}\n" + }, + "contracts/GraphTokenDistributor.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n/**\n * @title GraphTokenDistributor\n * @dev Contract that allows distribution of tokens to multiple beneficiaries.\n * The contract accept deposits in the configured token by anyone.\n * The owner can setup the desired distribution by setting the amount of tokens\n * assigned to each beneficiary account.\n * Beneficiaries claim for their allocated tokens.\n * Only the owner can withdraw tokens from this contract without limitations.\n * For the distribution to work this contract must be unlocked by the owner.\n */\ncontract GraphTokenDistributor is Ownable {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n // -- State --\n\n bool public locked;\n mapping(address => uint256) public beneficiaries;\n\n IERC20 public token;\n\n // -- Events --\n\n event BeneficiaryUpdated(address indexed beneficiary, uint256 amount);\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n event TokensClaimed(address indexed beneficiary, address to, uint256 amount);\n event LockUpdated(bool locked);\n\n modifier whenNotLocked() {\n require(locked == false, \"Distributor: Claim is locked\");\n _;\n }\n\n /**\n * Constructor.\n * @param _token Token to use for deposits and withdrawals\n */\n constructor(IERC20 _token) {\n token = _token;\n locked = true;\n }\n\n /**\n * Deposit tokens into the contract.\n * Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external {\n token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n // -- Admin functions --\n\n /**\n * Add token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function addBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].add(_amount));\n }\n\n /**\n * Add token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function addBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].add(_amounts[i]));\n }\n }\n\n /**\n * Remove token balance available for account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function subBeneficiaryTokens(address _account, uint256 _amount) external onlyOwner {\n _setBeneficiaryTokens(_account, beneficiaries[_account].sub(_amount));\n }\n\n /**\n * Remove token balance available for multiple accounts.\n * @param _accounts Addresses to assign tokens to\n * @param _amounts Amounts of tokens to assign to beneficiary\n */\n function subBeneficiaryTokensMulti(address[] calldata _accounts, uint256[] calldata _amounts) external onlyOwner {\n require(_accounts.length == _amounts.length, \"Distributor: !length\");\n for (uint256 i = 0; i < _accounts.length; i++) {\n _setBeneficiaryTokens(_accounts[i], beneficiaries[_accounts[i]].sub(_amounts[i]));\n }\n }\n\n /**\n * Set amount of tokens available for beneficiary account.\n * @param _account Address to assign tokens to\n * @param _amount Amount of tokens to assign to beneficiary\n */\n function _setBeneficiaryTokens(address _account, uint256 _amount) private {\n require(_account != address(0), \"Distributor: !account\");\n\n beneficiaries[_account] = _amount;\n emit BeneficiaryUpdated(_account, _amount);\n }\n\n /**\n * Set locked withdrawals.\n * @param _locked True to lock withdrawals\n */\n function setLocked(bool _locked) external onlyOwner {\n locked = _locked;\n emit LockUpdated(_locked);\n }\n\n /**\n * Withdraw tokens from the contract. This function is included as\n * a escape hatch in case of mistakes or to recover remaining funds.\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external onlyOwner {\n token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Beneficiary functions --\n\n /**\n * Claim tokens and send to caller.\n */\n function claim() external whenNotLocked {\n claimTo(msg.sender);\n }\n\n /**\n * Claim tokens and send to address.\n * @param _to Address where to send tokens\n */\n function claimTo(address _to) public whenNotLocked {\n uint256 claimableTokens = beneficiaries[msg.sender];\n require(claimableTokens > 0, \"Distributor: Unavailable funds\");\n\n _setBeneficiaryTokens(msg.sender, 0);\n\n token.safeTransfer(_to, claimableTokens);\n emit TokensClaimed(msg.sender, _to, claimableTokens);\n }\n}\n" + }, + "contracts/GraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport \"./MathUtils.sol\";\nimport \"./IGraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLock\n * @notice Contract that manages an unlocking schedule of tokens.\n * @dev The contract lock manage a number of tokens deposited into the contract to ensure that\n * they can only be released under certain time conditions.\n *\n * This contract implements a release scheduled based on periods and tokens are released in steps\n * after each period ends. It can be configured with one period in which case it is like a plain TimeLock.\n * It also supports revocation to be used for vesting schedules.\n *\n * The contract supports receiving extra funds than the managed tokens ones that can be\n * withdrawn by the beneficiary at any time.\n *\n * A releaseStartTime parameter is included to override the default release schedule and\n * perform the first release on the configured time. After that it will continue with the\n * default schedule.\n */\nabstract contract GraphTokenLock is OwnableInitializable, IGraphTokenLock {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n uint256 private constant MIN_PERIOD = 1;\n\n // -- State --\n\n IERC20 public token;\n address public beneficiary;\n\n // Configuration\n\n // Amount of tokens managed by the contract schedule\n uint256 public managedAmount;\n\n uint256 public startTime; // Start datetime (in unixtimestamp)\n uint256 public endTime; // Datetime after all funds are fully vested/unlocked (in unixtimestamp)\n uint256 public periods; // Number of vesting/release periods\n\n // First release date for tokens (in unixtimestamp)\n // If set, no tokens will be released before releaseStartTime ignoring\n // the amount to release each period\n uint256 public releaseStartTime;\n // A cliff set a date to which a beneficiary needs to get to vest\n // all preceding periods\n uint256 public vestingCliffTime;\n Revocability public revocable; // Whether to use vesting for locked funds\n\n // State\n\n bool public isRevoked;\n bool public isInitialized;\n bool public isAccepted;\n uint256 public releasedAmount;\n uint256 public revokedAmount;\n\n // -- Events --\n\n event TokensReleased(address indexed beneficiary, uint256 amount);\n event TokensWithdrawn(address indexed beneficiary, uint256 amount);\n event TokensRevoked(address indexed beneficiary, uint256 amount);\n event BeneficiaryChanged(address newBeneficiary);\n event LockAccepted();\n event LockCanceled();\n\n /**\n * @dev Only allow calls from the beneficiary of the contract\n */\n modifier onlyBeneficiary() {\n require(msg.sender == beneficiary, \"!auth\");\n _;\n }\n\n /**\n * @notice Initializes the contract\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _vestingCliffTime Override time for when the vesting start\n * @param _revocable Whether the contract is revocable\n */\n function _initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) internal {\n require(!isInitialized, \"Already initialized\");\n require(_owner != address(0), \"Owner cannot be zero\");\n require(_beneficiary != address(0), \"Beneficiary cannot be zero\");\n require(_token != address(0), \"Token cannot be zero\");\n require(_managedAmount > 0, \"Managed tokens cannot be zero\");\n require(_startTime != 0, \"Start time must be set\");\n require(_startTime < _endTime, \"Start time > end time\");\n require(_periods >= MIN_PERIOD, \"Periods cannot be below minimum\");\n require(_revocable != Revocability.NotSet, \"Must set a revocability option\");\n require(_releaseStartTime < _endTime, \"Release start time must be before end time\");\n require(_vestingCliffTime < _endTime, \"Cliff time must be before end time\");\n\n isInitialized = true;\n\n OwnableInitializable._initialize(_owner);\n beneficiary = _beneficiary;\n token = IERC20(_token);\n\n managedAmount = _managedAmount;\n\n startTime = _startTime;\n endTime = _endTime;\n periods = _periods;\n\n // Optionals\n releaseStartTime = _releaseStartTime;\n vestingCliffTime = _vestingCliffTime;\n revocable = _revocable;\n }\n\n /**\n * @notice Change the beneficiary of funds managed by the contract\n * @dev Can only be called by the beneficiary\n * @param _newBeneficiary Address of the new beneficiary address\n */\n function changeBeneficiary(address _newBeneficiary) external onlyBeneficiary {\n require(_newBeneficiary != address(0), \"Empty beneficiary\");\n beneficiary = _newBeneficiary;\n emit BeneficiaryChanged(_newBeneficiary);\n }\n\n /**\n * @notice Beneficiary accepts the lock, the owner cannot retrieve back the tokens\n * @dev Can only be called by the beneficiary\n */\n function acceptLock() external onlyBeneficiary {\n isAccepted = true;\n emit LockAccepted();\n }\n\n /**\n * @notice Owner cancel the lock and return the balance in the contract\n * @dev Can only be called by the owner\n */\n function cancelLock() external onlyOwner {\n require(isAccepted == false, \"Cannot cancel accepted contract\");\n\n token.safeTransfer(owner(), currentBalance());\n\n emit LockCanceled();\n }\n\n // -- Balances --\n\n /**\n * @notice Returns the amount of tokens currently held by the contract\n * @return Tokens held in the contract\n */\n function currentBalance() public view override returns (uint256) {\n return token.balanceOf(address(this));\n }\n\n // -- Time & Periods --\n\n /**\n * @notice Returns the current block timestamp\n * @return Current block timestamp\n */\n function currentTime() public view override returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @notice Gets duration of contract from start to end in seconds\n * @return Amount of seconds from contract startTime to endTime\n */\n function duration() public view override returns (uint256) {\n return endTime.sub(startTime);\n }\n\n /**\n * @notice Gets time elapsed since the start of the contract\n * @dev Returns zero if called before conctract starTime\n * @return Seconds elapsed from contract startTime\n */\n function sinceStartTime() public view override returns (uint256) {\n uint256 current = currentTime();\n if (current <= startTime) {\n return 0;\n }\n return current.sub(startTime);\n }\n\n /**\n * @notice Returns amount available to be released after each period according to schedule\n * @return Amount of tokens available after each period\n */\n function amountPerPeriod() public view override returns (uint256) {\n return managedAmount.div(periods);\n }\n\n /**\n * @notice Returns the duration of each period in seconds\n * @return Duration of each period in seconds\n */\n function periodDuration() public view override returns (uint256) {\n return duration().div(periods);\n }\n\n /**\n * @notice Gets the current period based on the schedule\n * @return A number that represents the current period\n */\n function currentPeriod() public view override returns (uint256) {\n return sinceStartTime().div(periodDuration()).add(MIN_PERIOD);\n }\n\n /**\n * @notice Gets the number of periods that passed since the first period\n * @return A number of periods that passed since the schedule started\n */\n function passedPeriods() public view override returns (uint256) {\n return currentPeriod().sub(MIN_PERIOD);\n }\n\n // -- Locking & Release Schedule --\n\n /**\n * @notice Gets the currently available token according to the schedule\n * @dev Implements the step-by-step schedule based on periods for available tokens\n * @return Amount of tokens available according to the schedule\n */\n function availableAmount() public view override returns (uint256) {\n uint256 current = currentTime();\n\n // Before contract start no funds are available\n if (current < startTime) {\n return 0;\n }\n\n // After contract ended all funds are available\n if (current > endTime) {\n return managedAmount;\n }\n\n // Get available amount based on period\n return passedPeriods().mul(amountPerPeriod());\n }\n\n /**\n * @notice Gets the amount of currently vested tokens\n * @dev Similar to available amount, but is fully vested when contract is non-revocable\n * @return Amount of tokens already vested\n */\n function vestedAmount() public view override returns (uint256) {\n // If non-revocable it is fully vested\n if (revocable == Revocability.Disabled) {\n return managedAmount;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n if (vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n return availableAmount();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule and takes into account already released tokens\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view virtual override returns (uint256) {\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n uint256 releasable = availableAmount().sub(releasedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Gets the outstanding amount yet to be released based on the whole contract lifetime\n * @dev Does not consider schedule but just global amounts tracked\n * @return Amount of outstanding tokens for the lifetime of the contract\n */\n function totalOutstandingAmount() public view override returns (uint256) {\n return managedAmount.sub(releasedAmount).sub(revokedAmount);\n }\n\n /**\n * @notice Gets surplus amount in the contract based on outstanding amount to release\n * @dev All funds over outstanding amount is considered surplus that can be withdrawn by beneficiary.\n * Note this might not be the correct value for wallets transferred to L2 (i.e. an L2GraphTokenLockWallet), as the released amount will be\n * skewed, so the beneficiary might have to bridge back to L1 to release the surplus.\n * @return Amount of tokens considered as surplus\n */\n function surplusAmount() public view override returns (uint256) {\n uint256 balance = currentBalance();\n uint256 outstandingAmount = totalOutstandingAmount();\n if (balance > outstandingAmount) {\n return balance.sub(outstandingAmount);\n }\n return 0;\n }\n\n // -- Value Transfer --\n\n /**\n * @notice Releases tokens based on the configured schedule\n * @dev All available releasable tokens are transferred to beneficiary\n */\n function release() external override onlyBeneficiary {\n uint256 amountToRelease = releasableAmount();\n require(amountToRelease > 0, \"No available releasable amount\");\n\n releasedAmount = releasedAmount.add(amountToRelease);\n\n token.safeTransfer(beneficiary, amountToRelease);\n\n emit TokensReleased(beneficiary, amountToRelease);\n }\n\n /**\n * @notice Withdraws surplus, unmanaged tokens from the contract\n * @dev Tokens in the contract over outstanding amount are considered as surplus\n * @param _amount Amount of tokens to withdraw\n */\n function withdrawSurplus(uint256 _amount) external override onlyBeneficiary {\n require(_amount > 0, \"Amount cannot be zero\");\n require(surplusAmount() >= _amount, \"Amount requested > surplus available\");\n\n token.safeTransfer(beneficiary, _amount);\n\n emit TokensWithdrawn(beneficiary, _amount);\n }\n\n /**\n * @notice Revokes a vesting schedule and return the unvested tokens to the owner\n * @dev Vesting schedule is always calculated based on managed tokens\n */\n function revoke() external override onlyOwner {\n require(revocable == Revocability.Enabled, \"Contract is non-revocable\");\n require(isRevoked == false, \"Already revoked\");\n\n uint256 unvestedAmount = managedAmount.sub(vestedAmount());\n require(unvestedAmount > 0, \"No available unvested amount\");\n\n revokedAmount = unvestedAmount;\n isRevoked = true;\n\n token.safeTransfer(owner(), unvestedAmount);\n\n emit TokensRevoked(beneficiary, unvestedAmount);\n }\n}\n" + }, + "contracts/GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/utils/EnumerableSet.sol\";\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./MinimalProxyFactory.sol\";\nimport \"./IGraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\n\n/**\n * @title GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract GraphTokenLockManager is Ownable, MinimalProxyFactory, IGraphTokenLockManager {\n using SafeERC20 for IERC20;\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // -- State --\n\n mapping(bytes4 => address) public authFnCalls;\n EnumerableSet.AddressSet private _tokenDestinations;\n\n address public masterCopy;\n IERC20 internal _token;\n\n // -- Events --\n\n event MasterCopyUpdated(address indexed masterCopy);\n event TokenLockCreated(\n address indexed contractAddress,\n bytes32 indexed initHash,\n address indexed beneficiary,\n address token,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n uint256 periods,\n uint256 releaseStartTime,\n uint256 vestingCliffTime,\n IGraphTokenLock.Revocability revocable\n );\n\n event TokensDeposited(address indexed sender, uint256 amount);\n event TokensWithdrawn(address indexed sender, uint256 amount);\n\n event FunctionCallAuth(address indexed caller, bytes4 indexed sigHash, address indexed target, string signature);\n event TokenDestinationAllowed(address indexed dst, bool allowed);\n\n /**\n * Constructor.\n * @param _graphToken Token to use for deposits and withdrawals\n * @param _masterCopy Address of the master copy to use to clone proxies\n */\n constructor(IERC20 _graphToken, address _masterCopy) {\n require(address(_graphToken) != address(0), \"Token cannot be zero\");\n _token = _graphToken;\n setMasterCopy(_masterCopy);\n }\n\n // -- Factory --\n\n /**\n * @notice Sets the masterCopy bytecode to use to create clones of TokenLock contracts\n * @param _masterCopy Address of contract bytecode to factory clone\n */\n function setMasterCopy(address _masterCopy) public override onlyOwner {\n require(_masterCopy != address(0), \"MasterCopy cannot be zero\");\n masterCopy = _masterCopy;\n emit MasterCopyUpdated(_masterCopy);\n }\n\n /**\n * @notice Creates and fund a new token lock wallet using a minimum proxy\n * @param _owner Address of the contract owner\n * @param _beneficiary Address of the beneficiary of locked tokens\n * @param _managedAmount Amount of tokens to be managed by the lock contract\n * @param _startTime Start time of the release schedule\n * @param _endTime End time of the release schedule\n * @param _periods Number of periods between start time and end time\n * @param _releaseStartTime Override time for when the releases start\n * @param _revocable Whether the contract is revocable\n */\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external override onlyOwner {\n require(_token.balanceOf(address(this)) >= _managedAmount, \"Not enough tokens to create lock\");\n\n // Create contract using a minimal proxy and call initializer\n bytes memory initializer = abi.encodeWithSelector(\n GraphTokenLockWallet.initialize.selector,\n address(this),\n _owner,\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n address contractAddress = _deployProxy2(keccak256(initializer), masterCopy, initializer);\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _managedAmount);\n\n emit TokenLockCreated(\n contractAddress,\n keccak256(initializer),\n _beneficiary,\n address(_token),\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n\n // -- Funds Management --\n\n /**\n * @notice Gets the GRT token address\n * @return Token used for transfers and approvals\n */\n function token() external view override returns (IERC20) {\n return _token;\n }\n\n /**\n * @notice Deposits tokens into the contract\n * @dev Even if the ERC20 token can be transferred directly to the contract\n * this function provide a safe interface to do the transfer and avoid mistakes\n * @param _amount Amount to deposit\n */\n function deposit(uint256 _amount) external override {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransferFrom(msg.sender, address(this), _amount);\n emit TokensDeposited(msg.sender, _amount);\n }\n\n /**\n * @notice Withdraws tokens from the contract\n * @dev Escape hatch in case of mistakes or to recover remaining funds\n * @param _amount Amount of tokens to withdraw\n */\n function withdraw(uint256 _amount) external override onlyOwner {\n require(_amount > 0, \"Amount cannot be zero\");\n _token.safeTransfer(msg.sender, _amount);\n emit TokensWithdrawn(msg.sender, _amount);\n }\n\n // -- Token Destinations --\n\n /**\n * @notice Adds an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function addTokenDestination(address _dst) external override onlyOwner {\n require(_dst != address(0), \"Destination cannot be zero\");\n require(_tokenDestinations.add(_dst), \"Destination already added\");\n emit TokenDestinationAllowed(_dst, true);\n }\n\n /**\n * @notice Removes an address that can be allowed by a token lock to pull funds\n * @param _dst Destination address\n */\n function removeTokenDestination(address _dst) external override onlyOwner {\n require(_tokenDestinations.remove(_dst), \"Destination already removed\");\n emit TokenDestinationAllowed(_dst, false);\n }\n\n /**\n * @notice Returns True if the address is authorized to be a destination of tokens\n * @param _dst Destination address\n * @return True if authorized\n */\n function isTokenDestination(address _dst) external view override returns (bool) {\n return _tokenDestinations.contains(_dst);\n }\n\n /**\n * @notice Returns an array of authorized destination addresses\n * @return Array of addresses authorized to pull funds from a token lock\n */\n function getTokenDestinations() external view override returns (address[] memory) {\n address[] memory dstList = new address[](_tokenDestinations.length());\n for (uint256 i = 0; i < _tokenDestinations.length(); i++) {\n dstList[i] = _tokenDestinations.at(i);\n }\n return dstList;\n }\n\n // -- Function Call Authorization --\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function setAuthFunctionCall(string calldata _signature, address _target) external override onlyOwner {\n _setAuthFunctionCall(_signature, _target);\n }\n\n /**\n * @notice Unsets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signature Function signature\n */\n function unsetAuthFunctionCall(string calldata _signature) external override onlyOwner {\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = address(0);\n\n emit FunctionCallAuth(msg.sender, sigHash, address(0), _signature);\n }\n\n /**\n * @notice Sets an authorized function call to target in bulk\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @param _signatures Function signatures\n * @param _targets Address of the destination contract to call\n */\n function setAuthFunctionCallMany(\n string[] calldata _signatures,\n address[] calldata _targets\n ) external override onlyOwner {\n require(_signatures.length == _targets.length, \"Array length mismatch\");\n\n for (uint256 i = 0; i < _signatures.length; i++) {\n _setAuthFunctionCall(_signatures[i], _targets[i]);\n }\n }\n\n /**\n * @notice Sets an authorized function call to target\n * @dev Input expected is the function signature as 'transfer(address,uint256)'\n * @dev Function signatures of Graph Protocol contracts to be used are known ahead of time\n * @param _signature Function signature\n * @param _target Address of the destination contract to call\n */\n function _setAuthFunctionCall(string calldata _signature, address _target) internal {\n require(_target != address(this), \"Target must be other contract\");\n require(Address.isContract(_target), \"Target must be a contract\");\n\n bytes4 sigHash = _toFunctionSigHash(_signature);\n authFnCalls[sigHash] = _target;\n\n emit FunctionCallAuth(msg.sender, sigHash, _target, _signature);\n }\n\n /**\n * @notice Gets the target contract to call for a particular function signature\n * @param _sigHash Function signature hash\n * @return Address of the target contract where to send the call\n */\n function getAuthFunctionCallTarget(bytes4 _sigHash) public view override returns (address) {\n return authFnCalls[_sigHash];\n }\n\n /**\n * @notice Returns true if the function call is authorized\n * @param _sigHash Function signature hash\n * @return True if authorized\n */\n function isAuthFunctionCall(bytes4 _sigHash) external view override returns (bool) {\n return getAuthFunctionCallTarget(_sigHash) != address(0);\n }\n\n /**\n * @dev Converts a function signature string to 4-bytes hash\n * @param _signature Function signature string\n * @return Function signature hash\n */\n function _toFunctionSigHash(string calldata _signature) internal pure returns (bytes4) {\n return _convertToBytes4(abi.encodeWithSignature(_signature));\n }\n\n /**\n * @dev Converts function signature bytes to function signature hash (bytes4)\n * @param _signature Function signature\n * @return Function signature in bytes4\n */\n function _convertToBytes4(bytes memory _signature) internal pure returns (bytes4) {\n require(_signature.length == 4, \"Invalid method signature\");\n bytes4 sigHash;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sigHash := mload(add(_signature, 32))\n }\n return sigHash;\n }\n}\n" + }, + "contracts/GraphTokenLockSimple.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"./GraphTokenLock.sol\";\n\n/**\n * @title GraphTokenLockSimple\n * @notice This contract is the concrete simple implementation built on top of the base\n * GraphTokenLock functionality for use when we only need the token lock schedule\n * features but no interaction with the network.\n *\n * This contract is designed to be deployed without the use of a TokenManager.\n */\ncontract GraphTokenLockSimple is GraphTokenLock {\n // Constructor\n constructor() {\n OwnableInitializable._initialize(msg.sender);\n }\n\n // Initializer\n function initialize(\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external onlyOwner {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n }\n}\n" + }, + "contracts/GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./GraphTokenLock.sol\";\nimport \"./IGraphTokenLockManager.sol\";\n\n/**\n * @title GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract GraphTokenLockWallet is GraphTokenLock {\n using SafeMath for uint256;\n\n // -- State --\n\n IGraphTokenLockManager public manager;\n uint256 public usedAmount;\n\n // -- Events --\n\n event ManagerUpdated(address indexed _oldManager, address indexed _newManager);\n event TokenDestinationsApproved();\n event TokenDestinationsRevoked();\n\n // Initializer\n function initialize(\n address _manager,\n address _owner,\n address _beneficiary,\n address _token,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n Revocability _revocable\n ) external {\n _initialize(\n _owner,\n _beneficiary,\n _token,\n _managedAmount,\n _startTime,\n _endTime,\n _periods,\n _releaseStartTime,\n _vestingCliffTime,\n _revocable\n );\n _setManager(_manager);\n }\n\n // -- Admin --\n\n /**\n * @notice Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function setManager(address _newManager) external onlyOwner {\n _setManager(_newManager);\n }\n\n /**\n * @dev Sets a new manager for this contract\n * @param _newManager Address of the new manager\n */\n function _setManager(address _newManager) internal {\n require(_newManager != address(0), \"Manager cannot be empty\");\n require(Address.isContract(_newManager), \"Manager must be a contract\");\n\n address oldManager = address(manager);\n manager = IGraphTokenLockManager(_newManager);\n\n emit ManagerUpdated(oldManager, _newManager);\n }\n\n // -- Beneficiary --\n\n /**\n * @notice Approves protocol access of the tokens managed by this contract\n * @dev Approves all token destinations registered in the manager to pull tokens\n */\n function approveProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe because we are using the max uint256 value\n token.approve(dstList[i], type(uint256).max);\n }\n emit TokenDestinationsApproved();\n }\n\n /**\n * @notice Revokes protocol access of the tokens managed by this contract\n * @dev Revokes approval to all token destinations in the manager to pull tokens\n */\n function revokeProtocol() external onlyBeneficiary {\n address[] memory dstList = manager.getTokenDestinations();\n for (uint256 i = 0; i < dstList.length; i++) {\n // Note this is only safe cause we're using 0 as the amount\n token.approve(dstList[i], 0);\n }\n emit TokenDestinationsRevoked();\n }\n\n /**\n * @notice Gets tokens currently available for release\n * @dev Considers the schedule, takes into account already released tokens and used amount\n * @return Amount of tokens ready to be released\n */\n function releasableAmount() public view override returns (uint256) {\n if (revocable == Revocability.Disabled) {\n return super.releasableAmount();\n }\n\n // -- Revocability enabled logic\n // This needs to deal with additional considerations for when tokens are used in the protocol\n\n // If a release start time is set no tokens are available for release before this date\n // If not set it follows the default schedule and tokens are available on\n // the first period passed\n if (releaseStartTime > 0 && currentTime() < releaseStartTime) {\n return 0;\n }\n\n // Vesting cliff is activated and it has not passed means nothing is vested yet\n // so funds cannot be released\n if (revocable == Revocability.Enabled && vestingCliffTime > 0 && currentTime() < vestingCliffTime) {\n return 0;\n }\n\n // A beneficiary can never have more releasable tokens than the contract balance\n // We consider the `usedAmount` in the protocol as part of the calculations\n // the beneficiary should not release funds that are used.\n uint256 releasable = availableAmount().sub(releasedAmount).sub(usedAmount);\n return MathUtils.min(currentBalance(), releasable);\n }\n\n /**\n * @notice Forward authorized contract calls to protocol contracts\n * @dev Fallback function can be called by the beneficiary only if function call is allowed\n */\n // solhint-disable-next-line no-complex-fallback\n fallback() external payable {\n // Only beneficiary can forward calls\n require(msg.sender == beneficiary, \"Unauthorized caller\");\n require(msg.value == 0, \"ETH transfers not supported\");\n\n // Function call validation\n address _target = manager.getAuthFunctionCallTarget(msg.sig);\n require(_target != address(0), \"Unauthorized function\");\n\n uint256 oldBalance = currentBalance();\n\n // Call function with data\n Address.functionCall(_target, msg.data);\n\n // Tracked used tokens in the protocol\n // We do this check after balances were updated by the forwarded call\n // Check is only enforced for revocable contracts to save some gas\n if (revocable == Revocability.Enabled) {\n // Track contract balance change\n uint256 newBalance = currentBalance();\n if (newBalance < oldBalance) {\n // Outflow\n uint256 diff = oldBalance.sub(newBalance);\n usedAmount = usedAmount.add(diff);\n } else {\n // Inflow: We can receive profits from the protocol, that could make usedAmount to\n // underflow. We set it to zero in that case.\n uint256 diff = newBalance.sub(oldBalance);\n usedAmount = (diff >= usedAmount) ? 0 : usedAmount.sub(diff);\n }\n require(usedAmount <= vestedAmount(), \"Cannot use more tokens than vested amount\");\n }\n }\n\n /**\n * @notice Receive function that always reverts.\n * @dev Only included to supress warnings, see https://github.com/ethereum/solidity/issues/10159\n */\n receive() external payable {\n revert(\"Bad call\");\n }\n}\n" + }, + "contracts/ICallhookReceiver.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\n// Copied from graphprotocol/contracts, changed solidity version to 0.7.3\n\n/**\n * @title Interface for contracts that can receive callhooks through the Arbitrum GRT bridge\n * @dev Any contract that can receive a callhook on L2, sent through the bridge from L1, must\n * be allowlisted by the governor, but also implement this interface that contains\n * the function that will actually be called by the L2GraphTokenGateway.\n */\npragma solidity ^0.7.3;\n\ninterface ICallhookReceiver {\n /**\n * @notice Receive tokens with a callhook from the bridge\n * @param _from Token sender in L1\n * @param _amount Amount of tokens that were transferred\n * @param _data ABI-encoded callhook data\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external;\n}\n" + }, + "contracts/IGraphTokenLock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IGraphTokenLock {\n enum Revocability {\n NotSet,\n Enabled,\n Disabled\n }\n\n // -- Balances --\n\n function currentBalance() external view returns (uint256);\n\n // -- Time & Periods --\n\n function currentTime() external view returns (uint256);\n\n function duration() external view returns (uint256);\n\n function sinceStartTime() external view returns (uint256);\n\n function amountPerPeriod() external view returns (uint256);\n\n function periodDuration() external view returns (uint256);\n\n function currentPeriod() external view returns (uint256);\n\n function passedPeriods() external view returns (uint256);\n\n // -- Locking & Release Schedule --\n\n function availableAmount() external view returns (uint256);\n\n function vestedAmount() external view returns (uint256);\n\n function releasableAmount() external view returns (uint256);\n\n function totalOutstandingAmount() external view returns (uint256);\n\n function surplusAmount() external view returns (uint256);\n\n // -- Value Transfer --\n\n function release() external;\n\n function withdrawSurplus(uint256 _amount) external;\n\n function revoke() external;\n}\n" + }, + "contracts/IGraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./IGraphTokenLock.sol\";\n\ninterface IGraphTokenLockManager {\n // -- Factory --\n\n function setMasterCopy(address _masterCopy) external;\n\n function createTokenLockWallet(\n address _owner,\n address _beneficiary,\n uint256 _managedAmount,\n uint256 _startTime,\n uint256 _endTime,\n uint256 _periods,\n uint256 _releaseStartTime,\n uint256 _vestingCliffTime,\n IGraphTokenLock.Revocability _revocable\n ) external;\n\n // -- Funds Management --\n\n function token() external returns (IERC20);\n\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _amount) external;\n\n // -- Allowed Funds Destinations --\n\n function addTokenDestination(address _dst) external;\n\n function removeTokenDestination(address _dst) external;\n\n function isTokenDestination(address _dst) external view returns (bool);\n\n function getTokenDestinations() external view returns (address[] memory);\n\n // -- Function Call Authorization --\n\n function setAuthFunctionCall(string calldata _signature, address _target) external;\n\n function unsetAuthFunctionCall(string calldata _signature) external;\n\n function setAuthFunctionCallMany(string[] calldata _signatures, address[] calldata _targets) external;\n\n function getAuthFunctionCallTarget(bytes4 _sigHash) external view returns (address);\n\n function isAuthFunctionCall(bytes4 _sigHash) external view returns (bool);\n}\n" + }, + "contracts/L1GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { AddressUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { MinimalProxyFactory } from \"./MinimalProxyFactory.sol\";\nimport { IGraphTokenLock } from \"./IGraphTokenLock.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { SafeMathUpgradeable } from \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol\";\nimport { Initializable } from \"@openzeppelin/contracts-upgradeable/proxy/Initializable.sol\";\n\n/**\n * @title L1GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from GraphTokenLockWallets\n * to a counterpart on L2. It is deployed on L1 and will send the GRT through\n * the L1GraphTokenGateway with a callhook to the L2GraphTokenLockManager, including\n * data to create a L2GraphTokenLockWallet on L2.\n *\n * Note that the L2GraphTokenLockWallet will not allow releasing any GRT until the end of\n * the vesting timeline, but will allow sending the GRT back to the L1 wallet.\n *\n * Beneficiaries for a GraphTokenLockWallet can perform the depositToL2Locked call\n * as many times as they want, and the GRT will be sent to the same L2GraphTokenLockWallet.\n *\n * Since all retryable tickets to send transactions to L2 require ETH for gas, this\n * contract also allows users to deposit ETH to be used for gas on L2, both for\n * the depositToL2Locked calls and for the transfer tools in the Staking contract for\n * The Graph.\n *\n * See GIP-0046 for more details: https://forum.thegraph.com/t/4023\n */\ncontract L1GraphTokenLockTransferTool is OwnableInitializable, Initializable, MinimalProxyFactory {\n using SafeMathUpgradeable for uint256;\n\n /// Address of the L1 GRT token contract\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenLockWallet implementation in L2, used to compute L2 wallet addresses\n address public immutable l2Implementation;\n /// Address of the L1GraphTokenGateway contract\n ITokenGateway public immutable l1Gateway;\n /// Address of the Staking contract, used to pull ETH for L2 ticket gas\n address payable public immutable staking;\n /// L2 lock manager for each L1 lock manager.\n /// L1 GraphTokenLockManager => L2GraphTokenLockManager\n mapping(address => address) public l2LockManager;\n /// L2 wallet owner for each L1 wallet owner.\n /// L1 wallet owner => L2 wallet owner\n mapping(address => address) public l2WalletOwner;\n /// L2 wallet address for each L1 wallet address.\n /// L1 wallet => L2 wallet\n mapping(address => address) public l2WalletAddress;\n /// ETH balance from each token lock, used to pay for L2 gas:\n /// L1 wallet address => ETH balance\n mapping(address => uint256) public tokenLockETHBalances;\n /// L2 beneficiary corresponding to each L1 wallet address.\n /// L1 wallet => L2 beneficiary\n mapping(address => address) public l2Beneficiary;\n /// Indicates whether an L2 wallet address for a wallet\n /// has been set manually, in which case it can't call depositToL2Locked.\n /// L1 wallet => bool\n mapping(address => bool) public l2WalletAddressSetManually;\n\n /// @dev Emitted when the L2 lock manager for an L1 lock manager is set\n event L2LockManagerSet(address indexed l1LockManager, address indexed l2LockManager);\n /// @dev Emitted when the L2 wallet owner for an L1 wallet owner is set\n event L2WalletOwnerSet(address indexed l1WalletOwner, address indexed l2WalletOwner);\n /// @dev Emitted when GRT is sent to L2 from a token lock\n event LockedFundsSentToL2(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l1LockManager,\n address l2LockManager,\n uint256 amount\n );\n /// @dev Emitted when an L2 wallet address is set for an L1 wallet\n event L2WalletAddressSet(address indexed l1Wallet, address indexed l2Wallet);\n /// @dev Emitted when ETH is deposited to a token lock's account\n event ETHDeposited(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when ETH is withdrawn from a token lock's account\n event ETHWithdrawn(address indexed tokenLock, address indexed destination, uint256 amount);\n /// @dev Emitted when ETH is pulled from a token lock's account by Staking or this tool to pay for an L2 ticket\n event ETHPulled(address indexed tokenLock, uint256 amount);\n /// @dev Emitted when the L2 beneficiary for a partially vested L1 lock is set\n event L2BeneficiarySet(address indexed l1Wallet, address indexed l2Beneficiary);\n\n /**\n * @notice Construct a new L1GraphTokenLockTransferTool contract\n * @dev The deployer of the contract will become its owner.\n * Note this contract is meant to be deployed behind a transparent proxy,\n * so this will run at the implementation's storage context; it will set\n * immutable variables and make the implementation be owned by the deployer.\n * @param _graphToken Address of the L1 GRT token contract\n * @param _l2Implementation Address of the L2GraphTokenLockWallet implementation in L2\n * @param _l1Gateway Address of the L1GraphTokenGateway contract\n * @param _staking Address of the Staking contract\n */\n constructor(\n IERC20 _graphToken,\n address _l2Implementation,\n ITokenGateway _l1Gateway,\n address payable _staking\n ) initializer {\n OwnableInitializable._initialize(msg.sender);\n graphToken = _graphToken;\n l2Implementation = _l2Implementation;\n l1Gateway = _l1Gateway;\n staking = _staking;\n }\n\n /**\n * @notice Initialize the L1GraphTokenLockTransferTool contract\n * @dev This function will run in the proxy's storage context, so it will\n * set the owner of the proxy contract which can be different from the implementation owner.\n * @param _owner Address of the owner of the L1GraphTokenLockTransferTool contract\n */\n function initialize(address _owner) external initializer {\n OwnableInitializable._initialize(_owner);\n }\n\n /**\n * @notice Set the L2 lock manager that corresponds to an L1 lock manager\n * @param _l1LockManager Address of the L1 lock manager\n * @param _l2LockManager Address of the L2 lock manager (in L2)\n */\n function setL2LockManager(address _l1LockManager, address _l2LockManager) external onlyOwner {\n l2LockManager[_l1LockManager] = _l2LockManager;\n emit L2LockManagerSet(_l1LockManager, _l2LockManager);\n }\n\n /**\n * @notice Set the L2 wallet owner that corresponds to an L1 wallet owner\n * @param _l1WalletOwner Address of the L1 wallet owner\n * @param _l2WalletOwner Address of the L2 wallet owner (in L2)\n */\n function setL2WalletOwner(address _l1WalletOwner, address _l2WalletOwner) external onlyOwner {\n l2WalletOwner[_l1WalletOwner] = _l2WalletOwner;\n emit L2WalletOwnerSet(_l1WalletOwner, _l2WalletOwner);\n }\n\n /**\n * @notice Deposit ETH on a token lock's account, to be used for L2 retryable ticket gas.\n * This function can be called by anyone, but the ETH will be credited to the token lock.\n * DO NOT try to call this through the token lock, as locks do not forward ETH value (and the\n * function call should not be allowlisted).\n * @param _tokenLock Address of the L1 GraphTokenLockWallet that will own the ETH\n */\n function depositETH(address _tokenLock) external payable {\n tokenLockETHBalances[_tokenLock] = tokenLockETHBalances[_tokenLock].add(msg.value);\n emit ETHDeposited(_tokenLock, msg.value);\n }\n\n /**\n * @notice Withdraw ETH from a token lock's account.\n * This function must be called from the token lock contract, but the destination\n * _must_ be a different address, as any ETH sent to the token lock would otherwise be\n * lost.\n * @param _destination Address to send the ETH\n * @param _amount Amount of ETH to send\n */\n function withdrawETH(address _destination, uint256 _amount) external {\n require(_amount > 0, \"INVALID_AMOUNT\");\n // We can't send eth to a token lock or it will be stuck\n require(msg.sender != _destination, \"INVALID_DESTINATION\");\n require(tokenLockETHBalances[msg.sender] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[msg.sender] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = payable(_destination).call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHWithdrawn(msg.sender, _destination, _amount);\n }\n\n /**\n * @notice Pull ETH from a token lock's account, to be used for L2 retryable ticket gas.\n * This can only be called by the Staking contract.\n * @param _tokenLock GraphTokenLockWallet that owns the ETH that will be debited\n * @param _amount Amount of ETH to pull\n */\n function pullETH(address _tokenLock, uint256 _amount) external {\n require(msg.sender == staking, \"ONLY_STAKING\");\n require(tokenLockETHBalances[_tokenLock] >= _amount, \"INSUFFICIENT_BALANCE\");\n tokenLockETHBalances[_tokenLock] -= _amount;\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, ) = staking.call{ value: _amount }(\"\");\n require(success, \"TRANSFER_FAILED\");\n emit ETHPulled(_tokenLock, _amount);\n }\n\n /**\n * @notice Deposit GRT to L2, from a token lock in L1 to a token lock in L2.\n * If the token lock in L2 does not exist, it will be created when the message is received\n * by the L2GraphTokenLockManager.\n * Before calling this (which must be done through the token lock wallet), make sure\n * there is enough ETH in the token lock's account to cover the L2 retryable ticket gas.\n * Note that L2 submission fee and gas refunds will be lost.\n * You can add ETH to the token lock's account by calling depositETH().\n * Note that after calling this, you will NOT be able to use setL2WalletAddressManually() to\n * set an L2 wallet address, as the L2 wallet address will be set automatically when the\n * message is received by the L2GraphTokenLockManager.\n * @dev The gas parameters for L2 can be estimated using the Arbitrum SDK.\n * @param _amount Amount of GRT to deposit\n * @param _l2Beneficiary Address of the beneficiary for the token lock in L2. Must be the same for subsequent calls of this function, and not an L1 contract.\n * @param _maxGas Maximum gas to use for the L2 retryable ticket\n * @param _gasPriceBid Gas price to use for the L2 retryable ticket\n * @param _maxSubmissionCost Max submission cost for the L2 retryable ticket\n */\n function depositToL2Locked(\n uint256 _amount,\n address _l2Beneficiary,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n uint256 _maxSubmissionCost\n ) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n require(wallet.revocable() != IGraphTokenLock.Revocability.Enabled, \"REVOCABLE\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n if (l2Beneficiary[msg.sender] == address(0)) {\n require(_l2Beneficiary != address(0), \"INVALID_BENEFICIARY_ZERO\");\n require(!AddressUpgradeable.isContract(_l2Beneficiary), \"INVALID_BENEFICIARY_CONTRACT\");\n l2Beneficiary[msg.sender] = _l2Beneficiary;\n emit L2BeneficiarySet(msg.sender, _l2Beneficiary);\n } else {\n require(l2Beneficiary[msg.sender] == _l2Beneficiary, \"INVALID_BENEFICIARY\");\n }\n\n uint256 expectedEth = _maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(tokenLockETHBalances[msg.sender] >= expectedEth, \"INSUFFICIENT_ETH_BALANCE\");\n tokenLockETHBalances[msg.sender] -= expectedEth;\n\n bytes memory encodedData;\n {\n address l2Owner = l2WalletOwner[wallet.owner()];\n require(l2Owner != address(0), \"L2_OWNER_NOT_SET\");\n // Extract all the storage variables from the GraphTokenLockWallet\n L2GraphTokenLockManager.TransferredWalletData memory data = L2GraphTokenLockManager.TransferredWalletData({\n l1Address: msg.sender,\n owner: l2Owner,\n beneficiary: l2Beneficiary[msg.sender],\n managedAmount: wallet.managedAmount(),\n startTime: wallet.startTime(),\n endTime: wallet.endTime()\n });\n encodedData = abi.encode(data);\n }\n\n if (l2WalletAddress[msg.sender] == address(0)) {\n require(wallet.endTime() >= block.timestamp, \"FULLY_VESTED_USE_MANUAL_ADDRESS\");\n address newAddress = getDeploymentAddress(keccak256(encodedData), l2Implementation, l2Manager);\n l2WalletAddress[msg.sender] = newAddress;\n emit L2WalletAddressSet(msg.sender, newAddress);\n } else {\n require(!l2WalletAddressSetManually[msg.sender], \"CANT_DEPOSIT_TO_MANUAL_ADDRESS\");\n }\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n\n // Send the tokens with a message through the L1GraphTokenGateway to the L2GraphTokenLockManager\n graphToken.approve(address(l1Gateway), _amount);\n {\n bytes memory transferData = abi.encode(_maxSubmissionCost, encodedData);\n l1Gateway.outboundTransfer{ value: expectedEth }(\n address(graphToken),\n l2Manager,\n _amount,\n _maxGas,\n _gasPriceBid,\n transferData\n );\n }\n emit ETHPulled(msg.sender, expectedEth);\n emit LockedFundsSentToL2(msg.sender, l2WalletAddress[msg.sender], l1Manager, l2Manager, _amount);\n }\n\n /**\n * @notice Manually set the L2 wallet address for a token lock in L1.\n * This will only work for token locks that have not been initialized in L2 yet, and\n * that are fully vested (endTime < current timestamp).\n * This address can then be used to send stake or delegation to L2 on the Staking contract.\n * After calling this, the vesting lock will NOT be allowed to use depositToL2Locked\n * to send GRT to L2, the beneficiary must withdraw the tokens and bridge them manually.\n * @param _l2Wallet Address of the L2 wallet\n */\n function setL2WalletAddressManually(address _l2Wallet) external {\n // Check that msg.sender is a GraphTokenLockWallet\n // That uses GRT and has a corresponding manager set in L2.\n GraphTokenLockWallet wallet = GraphTokenLockWallet(msg.sender);\n require(wallet.token() == graphToken, \"INVALID_TOKEN\");\n address l1Manager = address(wallet.manager());\n address l2Manager = l2LockManager[l1Manager];\n require(l2Manager != address(0), \"INVALID_MANAGER\");\n require(wallet.isInitialized(), \"!INITIALIZED\");\n\n // Check that the wallet is fully vested\n require(wallet.endTime() < block.timestamp, \"NOT_FULLY_VESTED\");\n\n // Check that the wallet has not set an L2 wallet yet\n require(l2WalletAddress[msg.sender] == address(0), \"L2_WALLET_ALREADY_SET\");\n\n // Check that the L2 address is not zero\n require(_l2Wallet != address(0), \"ZERO_ADDRESS\");\n // Set the L2 wallet address\n l2WalletAddress[msg.sender] = _l2Wallet;\n l2WalletAddressSetManually[msg.sender] = true;\n emit L2WalletAddressSet(msg.sender, _l2Wallet);\n }\n}\n" + }, + "contracts/L2GraphTokenLockManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\nimport { ICallhookReceiver } from \"./ICallhookReceiver.sol\";\nimport { GraphTokenLockManager } from \"./GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\n\n/**\n * @title L2GraphTokenLockManager\n * @notice This contract manages a list of authorized function calls and targets that can be called\n * by any TokenLockWallet contract and it is a factory of TokenLockWallet contracts.\n *\n * This contract receives funds to make the process of creating TokenLockWallet contracts\n * easier by distributing them the initial tokens to be managed.\n *\n * In particular, this L2 variant is designed to receive token lock wallets from L1,\n * through the GRT bridge. These transferred wallets will not allow releasing funds in L2 until\n * the end of the vesting timeline, but they can allow withdrawing funds back to L1 using\n * the L2GraphTokenLockTransferTool contract.\n *\n * The owner can setup a list of token destinations that will be used by TokenLock contracts to\n * approve the pulling of funds, this way in can be guaranteed that only protocol contracts\n * will manipulate users funds.\n */\ncontract L2GraphTokenLockManager is GraphTokenLockManager, ICallhookReceiver {\n using SafeERC20 for IERC20;\n\n /// @dev Struct to hold the data of a transferred wallet; this is\n /// the data that must be encoded in L1 to send a wallet to L2.\n struct TransferredWalletData {\n address l1Address;\n address owner;\n address beneficiary;\n uint256 managedAmount;\n uint256 startTime;\n uint256 endTime;\n }\n\n /// Address of the L2GraphTokenGateway\n address public immutable l2Gateway;\n /// Address of the L1 transfer tool contract (in L1, no aliasing)\n address public immutable l1TransferTool;\n /// Mapping of each L1 wallet to its L2 wallet counterpart (populated when each wallet is received)\n /// L1 address => L2 address\n mapping(address => address) public l1WalletToL2Wallet;\n /// Mapping of each L2 wallet to its L1 wallet counterpart (populated when each wallet is received)\n /// L2 address => L1 address\n mapping(address => address) public l2WalletToL1Wallet;\n\n /// @dev Event emitted when a wallet is received and created from L1\n event TokenLockCreatedFromL1(\n address indexed contractAddress,\n bytes32 initHash,\n address indexed beneficiary,\n uint256 managedAmount,\n uint256 startTime,\n uint256 endTime,\n address indexed l1Address\n );\n\n /// @dev Emitted when locked tokens are received from L1 (whether the wallet\n /// had already been received or not)\n event LockedTokensReceivedFromL1(address indexed l1Address, address indexed l2Address, uint256 amount);\n\n /**\n * @dev Checks that the sender is the L2GraphTokenGateway.\n */\n modifier onlyL2Gateway() {\n require(msg.sender == l2Gateway, \"ONLY_GATEWAY\");\n _;\n }\n\n /**\n * @notice Constructor for the L2GraphTokenLockManager contract.\n * @param _graphToken Address of the L2 GRT token contract\n * @param _masterCopy Address of the master copy of the L2GraphTokenLockWallet implementation\n * @param _l2Gateway Address of the L2GraphTokenGateway contract\n * @param _l1TransferTool Address of the L1 transfer tool contract (in L1, without aliasing)\n */\n constructor(\n IERC20 _graphToken,\n address _masterCopy,\n address _l2Gateway,\n address _l1TransferTool\n ) GraphTokenLockManager(_graphToken, _masterCopy) {\n l2Gateway = _l2Gateway;\n l1TransferTool = _l1TransferTool;\n }\n\n /**\n * @notice This function is called by the L2GraphTokenGateway when tokens are sent from L1.\n * @dev This function will create a new wallet if it doesn't exist yet, or send the tokens to\n * the existing wallet if it does.\n * @param _from Address of the sender in L1, which must be the L1GraphTokenLockTransferTool\n * @param _amount Amount of tokens received\n * @param _data Encoded data of the transferred wallet, which must be an ABI-encoded TransferredWalletData struct\n */\n function onTokenTransfer(address _from, uint256 _amount, bytes calldata _data) external override onlyL2Gateway {\n require(_from == l1TransferTool, \"ONLY_TRANSFER_TOOL\");\n TransferredWalletData memory walletData = abi.decode(_data, (TransferredWalletData));\n\n if (l1WalletToL2Wallet[walletData.l1Address] != address(0)) {\n // If the wallet was already received, just send the tokens to the L2 address\n _token.safeTransfer(l1WalletToL2Wallet[walletData.l1Address], _amount);\n } else {\n // Create contract using a minimal proxy and call initializer\n (bytes32 initHash, address contractAddress) = _deployFromL1(keccak256(_data), walletData);\n l1WalletToL2Wallet[walletData.l1Address] = contractAddress;\n l2WalletToL1Wallet[contractAddress] = walletData.l1Address;\n\n // Send managed amount to the created contract\n _token.safeTransfer(contractAddress, _amount);\n\n emit TokenLockCreatedFromL1(\n contractAddress,\n initHash,\n walletData.beneficiary,\n walletData.managedAmount,\n walletData.startTime,\n walletData.endTime,\n walletData.l1Address\n );\n }\n emit LockedTokensReceivedFromL1(walletData.l1Address, l1WalletToL2Wallet[walletData.l1Address], _amount);\n }\n\n /**\n * @dev Deploy a token lock wallet with data received from L1\n * @param _salt Salt for the CREATE2 call, which must be the hash of the wallet data\n * @param _walletData Data of the wallet to be created\n * @return Hash of the initialization calldata\n * @return Address of the created contract\n */\n function _deployFromL1(bytes32 _salt, TransferredWalletData memory _walletData) internal returns (bytes32, address) {\n bytes memory initializer = _encodeInitializer(_walletData);\n address contractAddress = _deployProxy2(_salt, masterCopy, initializer);\n return (keccak256(initializer), contractAddress);\n }\n\n /**\n * @dev Encode the initializer for the token lock wallet received from L1\n * @param _walletData Data of the wallet to be created\n * @return Encoded initializer calldata, including the function signature\n */\n function _encodeInitializer(TransferredWalletData memory _walletData) internal view returns (bytes memory) {\n return\n abi.encodeWithSelector(\n L2GraphTokenLockWallet.initializeFromL1.selector,\n address(this),\n address(_token),\n _walletData\n );\n }\n}\n" + }, + "contracts/L2GraphTokenLockTransferTool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\nimport { L2GraphTokenLockWallet } from \"./L2GraphTokenLockWallet.sol\";\nimport { ITokenGateway } from \"./arbitrum/ITokenGateway.sol\";\n\n/**\n * @title L2GraphTokenLockTransferTool contract\n * @notice This contract is used to transfer GRT from L2 token lock wallets\n * back to their L1 counterparts.\n */\ncontract L2GraphTokenLockTransferTool {\n /// Address of the L2 GRT token\n IERC20 public immutable graphToken;\n /// Address of the L2GraphTokenGateway\n ITokenGateway public immutable l2Gateway;\n /// Address of the L1 GRT token (in L1, no aliasing)\n address public immutable l1GraphToken;\n\n /// @dev Emitted when GRT is sent to L1 from a token lock\n event LockedFundsSentToL1(\n address indexed l1Wallet,\n address indexed l2Wallet,\n address indexed l2LockManager,\n uint256 amount\n );\n\n /**\n * @notice Constructor for the L2GraphTokenLockTransferTool contract\n * @dev Note the L2GraphTokenLockTransferTool can be deployed behind a proxy,\n * and the constructor for the implementation will only set some immutable\n * variables.\n * @param _graphToken Address of the L2 GRT token\n * @param _l2Gateway Address of the L2GraphTokenGateway\n * @param _l1GraphToken Address of the L1 GRT token (in L1, no aliasing)\n */\n constructor(IERC20 _graphToken, ITokenGateway _l2Gateway, address _l1GraphToken) {\n graphToken = _graphToken;\n l2Gateway = _l2Gateway;\n l1GraphToken = _l1GraphToken;\n }\n\n /**\n * @notice Withdraw GRT from an L2 token lock wallet to its L1 counterpart.\n * This function must be called from an L2GraphTokenLockWallet contract.\n * The GRT will be sent to L1 and must be claimed using the Arbitrum Outbox on L1\n * after the standard Arbitrum withdrawal period (7 days).\n * @param _amount Amount of GRT to withdraw\n */\n function withdrawToL1Locked(uint256 _amount) external {\n L2GraphTokenLockWallet wallet = L2GraphTokenLockWallet(msg.sender);\n L2GraphTokenLockManager manager = L2GraphTokenLockManager(address(wallet.manager()));\n require(address(manager) != address(0), \"INVALID_SENDER\");\n address l1Wallet = manager.l2WalletToL1Wallet(msg.sender);\n require(l1Wallet != address(0), \"NOT_L1_WALLET\");\n require(_amount <= graphToken.balanceOf(msg.sender), \"INSUFFICIENT_BALANCE\");\n require(_amount != 0, \"ZERO_AMOUNT\");\n\n graphToken.transferFrom(msg.sender, address(this), _amount);\n graphToken.approve(address(l2Gateway), _amount);\n\n // Send the tokens through the L2GraphTokenGateway to the L1 wallet counterpart\n l2Gateway.outboundTransfer(l1GraphToken, l1Wallet, _amount, 0, 0, \"\");\n emit LockedFundsSentToL1(l1Wallet, msg.sender, address(manager), _amount);\n }\n}\n" + }, + "contracts/L2GraphTokenLockWallet.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport { GraphTokenLockWallet } from \"./GraphTokenLockWallet.sol\";\nimport { Ownable as OwnableInitializable } from \"./Ownable.sol\";\nimport { L2GraphTokenLockManager } from \"./L2GraphTokenLockManager.sol\";\n\n/**\n * @title L2GraphTokenLockWallet\n * @notice This contract is built on top of the base GraphTokenLock functionality.\n * It allows wallet beneficiaries to use the deposited funds to perform specific function calls\n * on specific contracts.\n *\n * The idea is that supporters with locked tokens can participate in the protocol\n * but disallow any release before the vesting/lock schedule.\n * The beneficiary can issue authorized function calls to this contract that will\n * get forwarded to a target contract. A target contract is any of our protocol contracts.\n * The function calls allowed are queried to the GraphTokenLockManager, this way\n * the same configuration can be shared for all the created lock wallet contracts.\n *\n * This L2 variant includes a special initializer so that it can be created from\n * a wallet's data received from L1. These transferred wallets will not allow releasing\n * funds in L2 until the end of the vesting timeline, but they can allow withdrawing\n * funds back to L1 using the L2GraphTokenLockTransferTool contract.\n *\n * Note that surplusAmount and releasedAmount in L2 will be skewed for wallets received from L1,\n * so releasing surplus tokens might also only be possible by bridging tokens back to L1.\n *\n * NOTE: Contracts used as target must have its function signatures checked to avoid collisions\n * with any of this contract functions.\n * Beneficiaries need to approve the use of the tokens to the protocol contracts. For convenience\n * the maximum amount of tokens is authorized.\n * Function calls do not forward ETH value so DO NOT SEND ETH TO THIS CONTRACT.\n */\ncontract L2GraphTokenLockWallet is GraphTokenLockWallet {\n // Initializer when created from a message from L1\n function initializeFromL1(\n address _manager,\n address _token,\n L2GraphTokenLockManager.TransferredWalletData calldata _walletData\n ) external {\n require(!isInitialized, \"Already initialized\");\n isInitialized = true;\n\n OwnableInitializable._initialize(_walletData.owner);\n beneficiary = _walletData.beneficiary;\n token = IERC20(_token);\n\n managedAmount = _walletData.managedAmount;\n\n startTime = _walletData.startTime;\n endTime = _walletData.endTime;\n periods = 1;\n isAccepted = true;\n\n // Optionals\n releaseStartTime = _walletData.endTime;\n revocable = Revocability.Disabled;\n\n _setManager(_manager);\n }\n}\n" + }, + "contracts/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nlibrary MathUtils {\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/MinimalProxyFactory.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { Create2 } from \"@openzeppelin/contracts/utils/Create2.sol\";\n\n/**\n * @title MinimalProxyFactory: a factory contract for creating minimal proxies\n * @notice Adapted from https://github.com/OpenZeppelin/openzeppelin-sdk/blob/v2.5.0/packages/lib/contracts/upgradeability/ProxyFactory.sol\n * Based on https://eips.ethereum.org/EIPS/eip-1167\n */\ncontract MinimalProxyFactory {\n /// @dev Emitted when a new proxy is created\n event ProxyCreated(address indexed proxy);\n\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @dev Uses address(this) as deployer to compute the address. Only for backwards compatibility.\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation\n ) public view returns (address) {\n return getDeploymentAddress(_salt, _implementation, address(this));\n }\n\n /**\n * @notice Gets the deterministic CREATE2 address for MinimalProxy with a particular implementation\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _deployer Address of the deployer that creates the contract\n * @return Address of the counterfactual MinimalProxy\n */\n function getDeploymentAddress(\n bytes32 _salt,\n address _implementation,\n address _deployer\n ) public pure returns (address) {\n return Create2.computeAddress(_salt, keccak256(_getContractCreationCode(_implementation)), _deployer);\n }\n\n /**\n * @dev Deploys a MinimalProxy with CREATE2\n * @param _salt Bytes32 salt to use for CREATE2\n * @param _implementation Address of the proxy target implementation\n * @param _data Bytes with the initializer call\n * @return Address of the deployed MinimalProxy\n */\n function _deployProxy2(bytes32 _salt, address _implementation, bytes memory _data) internal returns (address) {\n address proxyAddress = Create2.deploy(0, _salt, _getContractCreationCode(_implementation));\n\n emit ProxyCreated(proxyAddress);\n\n // Call function with data\n if (_data.length > 0) {\n Address.functionCall(proxyAddress, _data);\n }\n\n return proxyAddress;\n }\n\n /**\n * @dev Gets the MinimalProxy bytecode\n * @param _implementation Address of the proxy target implementation\n * @return MinimalProxy bytecode\n */\n function _getContractCreationCode(address _implementation) internal pure returns (bytes memory) {\n bytes10 creation = 0x3d602d80600a3d3981f3;\n bytes10 prefix = 0x363d3d373d3d3d363d73;\n bytes20 targetBytes = bytes20(_implementation);\n bytes15 suffix = 0x5af43d82803e903d91602b57fd5bf3;\n return abi.encodePacked(creation, prefix, targetBytes, suffix);\n }\n}\n" + }, + "contracts/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * The owner account will be passed on initialization of the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n /// @dev Owner of the contract, can be retrieved with the public owner() function\n address private _owner;\n /// @dev Since upgradeable contracts might inherit this, we add a storage gap\n /// to allow adding variables here without breaking the proxy storage layout\n uint256[50] private __gap;\n\n /// @dev Emitted when ownership of the contract is transferred\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function _initialize(address owner) internal {\n _owner = owner;\n emit OwnershipTransferred(address(0), owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(_owner == msg.sender, \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() external virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) external virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n" + }, + "contracts/tests/arbitrum/AddressAliasHelper.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2019-2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/84e64dee6ee82adbf8ec34fd4b86c207a61d9007/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nlibrary AddressAliasHelper {\n uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);\n\n /// @notice Utility function that converts the address in the L1 that submitted a tx to\n /// the inbox to the msg.sender viewed in the L2\n /// @param l1Address the address in the L1 that triggered the tx to L2\n /// @return l2Address L2 address as viewed in msg.sender\n function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {\n l2Address = address(uint160(l1Address) + offset);\n }\n\n /// @notice Utility function that converts the msg.sender viewed in the L2 to the\n /// address in the L1 that submitted a tx to the inbox\n /// @param l2Address L2 address as viewed in msg.sender\n /// @return l1Address the address in the L1 that triggered the tx to L2\n function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {\n l1Address = address(uint160(l2Address) - offset);\n }\n}\n" + }, + "contracts/tests/arbitrum/IBridge.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IBridge {\n event MessageDelivered(\n uint256 indexed messageIndex,\n bytes32 indexed beforeInboxAcc,\n address inbox,\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n );\n\n event BridgeCallTriggered(address indexed outbox, address indexed destAddr, uint256 amount, bytes data);\n\n event InboxToggle(address indexed inbox, bool enabled);\n\n event OutboxToggle(address indexed outbox, bool enabled);\n\n function deliverMessageToInbox(\n uint8 kind,\n address sender,\n bytes32 messageDataHash\n ) external payable returns (uint256);\n\n function executeCall(\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (bool success, bytes memory returnData);\n\n // These are only callable by the admin\n function setInbox(address inbox, bool enabled) external;\n\n function setOutbox(address inbox, bool enabled) external;\n\n // View functions\n\n function activeOutbox() external view returns (address);\n\n function allowedInboxes(address inbox) external view returns (bool);\n\n function allowedOutboxes(address outbox) external view returns (bool);\n\n function inboxAccs(uint256 index) external view returns (bytes32);\n\n function messageCount() external view returns (uint256);\n}\n" + }, + "contracts/tests/arbitrum/IInbox.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\nimport \"./IBridge.sol\";\nimport \"./IMessageProvider.sol\";\n\ninterface IInbox is IMessageProvider {\n function sendL2Message(bytes calldata messageData) external returns (uint256);\n\n function sendUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n uint256 amount,\n bytes calldata data\n ) external returns (uint256);\n\n function sendL1FundedUnsignedTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 nonce,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function sendL1FundedContractTransaction(\n uint256 maxGas,\n uint256 gasPriceBid,\n address destAddr,\n bytes calldata data\n ) external payable returns (uint256);\n\n function createRetryableTicket(\n address destAddr,\n uint256 arbTxCallValue,\n uint256 maxSubmissionCost,\n address submissionRefundAddress,\n address valueRefundAddress,\n uint256 maxGas,\n uint256 gasPriceBid,\n bytes calldata data\n ) external payable returns (uint256);\n\n function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);\n\n function bridge() external view returns (IBridge);\n\n function pauseCreateRetryables() external;\n\n function unpauseCreateRetryables() external;\n\n function startRewriteAddress() external;\n\n function stopRewriteAddress() external;\n}\n" + }, + "contracts/tests/arbitrum/IMessageProvider.sol": { + "content": "// SPDX-License-Identifier: Apache-2.0\n\n/*\n * Copyright 2021, Offchain Labs, Inc.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * Originally copied from:\n * https://github.com/OffchainLabs/arbitrum/tree/e3a6307ad8a2dc2cad35728a2a9908cfd8dd8ef9/packages/arb-bridge-eth\n *\n * MODIFIED from Offchain Labs' implementation:\n * - Changed solidity version to 0.7.3 (pablo@edgeandnode.com)\n *\n */\n\npragma solidity ^0.7.3;\n\ninterface IMessageProvider {\n event InboxMessageDelivered(uint256 indexed messageNum, bytes data);\n\n event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);\n}\n" + }, + "contracts/tests/BridgeMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IBridge.sol\";\n\n/**\n * @title Arbitrum Bridge mock contract\n * @dev This contract implements Arbitrum's IBridge interface for testing purposes\n */\ncontract BridgeMock is IBridge {\n /// Address of the (mock) Arbitrum Inbox\n address public inbox;\n /// Address of the (mock) Arbitrum Outbox\n address public outbox;\n /// Index of the next message on the inbox messages array\n uint256 public messageIndex;\n /// Inbox messages array\n bytes32[] public override inboxAccs;\n\n /**\n * @notice Deliver a message to the inbox. The encoded message will be\n * added to the inbox array, and messageIndex will be incremented.\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the message data\n * @return The next index for the inbox array\n */\n function deliverMessageToInbox(\n uint8 _kind,\n address _sender,\n bytes32 _messageDataHash\n ) external payable override returns (uint256) {\n messageIndex = messageIndex + 1;\n inboxAccs.push(keccak256(abi.encodePacked(inbox, _kind, _sender, _messageDataHash)));\n emit MessageDelivered(messageIndex, inboxAccs[messageIndex - 1], msg.sender, _kind, _sender, _messageDataHash);\n return messageIndex;\n }\n\n /**\n * @notice Executes an L1 function call incoing from L2. This can only be called\n * by the Outbox.\n * @param _destAddr Contract to call\n * @param _amount ETH value to send\n * @param _data Calldata for the function call\n * @return True if the call was successful, false otherwise\n * @return Return data from the call\n */\n function executeCall(\n address _destAddr,\n uint256 _amount,\n bytes calldata _data\n ) external override returns (bool, bytes memory) {\n require(outbox == msg.sender, \"NOT_FROM_OUTBOX\");\n bool success;\n bytes memory returnData;\n\n // solhint-disable-next-line avoid-low-level-calls\n (success, returnData) = _destAddr.call{ value: _amount }(_data);\n emit BridgeCallTriggered(msg.sender, _destAddr, _amount, _data);\n return (success, returnData);\n }\n\n /**\n * @notice Set the address of the inbox. Anyone can call this, because it's a mock.\n * @param _inbox Address of the inbox\n * @param _enabled Enable the inbox (ignored)\n */\n function setInbox(address _inbox, bool _enabled) external override {\n inbox = _inbox;\n emit InboxToggle(inbox, _enabled);\n }\n\n /**\n * @notice Set the address of the outbox. Anyone can call this, because it's a mock.\n * @param _outbox Address of the outbox\n * @param _enabled Enable the outbox (ignored)\n */\n function setOutbox(address _outbox, bool _enabled) external override {\n outbox = _outbox;\n emit OutboxToggle(outbox, _enabled);\n }\n\n // View functions\n\n /**\n * @notice Getter for the active outbox (in this case there's only one)\n */\n function activeOutbox() external view override returns (address) {\n return outbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed inbox (in this case there's only one)\n * @param _inbox Address to check\n * @return True if the address is the allowed inbox, false otherwise\n */\n function allowedInboxes(address _inbox) external view override returns (bool) {\n return _inbox == inbox;\n }\n\n /**\n * @notice Getter for whether an address is an allowed outbox (in this case there's only one)\n * @param _outbox Address to check\n * @return True if the address is the allowed outbox, false otherwise\n */\n function allowedOutboxes(address _outbox) external view override returns (bool) {\n return _outbox == outbox;\n }\n\n /**\n * @notice Getter for the count of messages in the inboxAccs\n * @return Number of messages in inboxAccs\n */\n function messageCount() external view override returns (uint256) {\n return inboxAccs.length;\n }\n}\n" + }, + "contracts/tests/GraphTokenMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title Graph Token Mock contract.\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract GraphTokenMock is Ownable, ERC20 {\n /**\n * @notice Contract Constructor.\n * @param _initialSupply Initial supply\n * @param _mintTo Address to whitch to mint the initial supply\n */\n constructor(uint256 _initialSupply, address _mintTo) ERC20(\"Graph Token Mock\", \"GRT-Mock\") {\n // Deploy to mint address\n _mint(_mintTo, _initialSupply);\n }\n\n /**\n * @notice Mint tokens to an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _to Address to mint tokens to\n * @param _amount Amount of tokens to mint\n */\n function bridgeMint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n\n /**\n * @notice Burn tokens from an address from the bridge.\n * (The real one has an onlyGateway modifier)\n * @param _from Address to burn tokens from\n * @param _amount Amount of tokens to burn\n */\n function bridgeBurn(address _from, uint256 _amount) external {\n _burn(_from, _amount);\n }\n}\n" + }, + "contracts/tests/InboxMock.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\n\nimport \"./arbitrum/IInbox.sol\";\nimport \"./arbitrum/AddressAliasHelper.sol\";\n\n/**\n * @title Arbitrum Inbox mock contract\n * @dev This contract implements (a subset of) Arbitrum's IInbox interface for testing purposes\n */\ncontract InboxMock is IInbox {\n /// @dev Type indicator for a standard L2 message\n uint8 internal constant L2_MSG = 3;\n /// @dev Type indicator for a retryable ticket message\n // solhint-disable-next-line const-name-snakecase\n uint8 internal constant L1MessageType_submitRetryableTx = 9;\n /// Address of the Bridge (mock) contract\n IBridge public override bridge;\n\n /**\n * @notice Send a message to L2 (by delivering it to the Bridge)\n * @param _messageData Encoded data to send in the message\n * @return Message number returned by the inbox\n */\n function sendL2Message(bytes calldata _messageData) external override returns (uint256) {\n uint256 msgNum = deliverToBridge(L2_MSG, msg.sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @notice Set the address of the (mock) bridge\n * @param _bridge Address of the bridge\n */\n function setBridge(address _bridge) external {\n bridge = IBridge(_bridge);\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendContractTransaction(\n uint256,\n uint256,\n address,\n uint256,\n bytes calldata\n ) external pure override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedUnsignedTransaction(\n uint256,\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function sendL1FundedContractTransaction(\n uint256,\n uint256,\n address,\n bytes calldata\n ) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Creates a retryable ticket for an L2 transaction\n * @param _destAddr Address of the contract to call in L2\n * @param _arbTxCallValue Callvalue to use in the L2 transaction\n * @param _maxSubmissionCost Max cost of submitting the ticket, in Wei\n * @param _submissionRefundAddress L2 address to refund for any remaining value from the submission cost\n * @param _valueRefundAddress L2 address to refund if the ticket times out or gets cancelled\n * @param _maxGas Max gas for the L2 transcation\n * @param _gasPriceBid Gas price bid on L2\n * @param _data Encoded calldata for the L2 transaction (including function selector)\n * @return Message number returned by the bridge\n */\n function createRetryableTicket(\n address _destAddr,\n uint256 _arbTxCallValue,\n uint256 _maxSubmissionCost,\n address _submissionRefundAddress,\n address _valueRefundAddress,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable override returns (uint256) {\n _submissionRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_submissionRefundAddress);\n _valueRefundAddress = AddressAliasHelper.applyL1ToL2Alias(_valueRefundAddress);\n return\n _deliverMessage(\n L1MessageType_submitRetryableTx,\n msg.sender,\n abi.encodePacked(\n uint256(uint160(bytes20(_destAddr))),\n _arbTxCallValue,\n msg.value,\n _maxSubmissionCost,\n uint256(uint160(bytes20(_submissionRefundAddress))),\n uint256(uint160(bytes20(_valueRefundAddress))),\n _maxGas,\n _gasPriceBid,\n _data.length,\n _data\n )\n );\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function depositEth(uint256) external payable override returns (uint256) {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function pauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function unpauseCreateRetryables() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function startRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @notice Unimplemented in this mock\n */\n function stopRewriteAddress() external pure override {\n revert(\"Unimplemented\");\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageData Encoded message data\n * @return Message number returned by the bridge\n */\n function _deliverMessage(uint8 _kind, address _sender, bytes memory _messageData) internal returns (uint256) {\n uint256 msgNum = deliverToBridge(_kind, _sender, keccak256(_messageData));\n emit InboxMessageDelivered(msgNum, _messageData);\n return msgNum;\n }\n\n /**\n * @dev Deliver a message to the bridge\n * @param _kind Type of the message\n * @param _sender Address that is sending the message\n * @param _messageDataHash keccak256 hash of the encoded message data\n * @return Message number returned by the bridge\n */\n function deliverToBridge(uint8 _kind, address _sender, bytes32 _messageDataHash) internal returns (uint256) {\n return bridge.deliverMessageToInbox{ value: msg.value }(_kind, _sender, _messageDataHash);\n }\n}\n" + }, + "contracts/tests/L1TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\n\n/**\n * @title L1 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L1TokenGatewayMock is Ownable {\n using SafeMath for uint256;\n /// Next sequence number to return when outboundTransfer is called\n uint256 public nextSeqNum;\n\n /// @dev Emitted when a (fake) retryable ticket is created\n event FakeTxToL2(\n address from,\n uint256 value,\n uint256 maxGas,\n uint256 gasPriceBid,\n uint256 maxSubmissionCost,\n bytes outboundCalldata\n );\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are deposited from L1 to L2\n event DepositInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L1 Token Gateway Contract Constructor.\n */\n constructor() {}\n\n /**\n * @notice Creates and sends a fake retryable ticket to transfer GRT to L2.\n * This mock will actually just emit an event with parameters equivalent to what the real L1GraphTokenGateway\n * would send to L2.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _maxGas Gas limit for L2 execution of the ticket\n * @param _gasPriceBid Price per gas on L2\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return Sequence number of the retryable ticket created by Inbox (always )\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256 _maxGas,\n uint256 _gasPriceBid,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 seqNum = nextSeqNum;\n nextSeqNum += 1;\n {\n uint256 maxSubmissionCost;\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, maxSubmissionCost, extraData) = _parseOutboundData(_data);\n require(maxSubmissionCost > 0, \"NO_SUBMISSION_COST\");\n\n {\n // makes sure only sufficient ETH is supplied as required for successful redemption on L2\n // if a user does not desire immediate redemption they should provide\n // a msg.value of AT LEAST maxSubmissionCost\n uint256 expectedEth = maxSubmissionCost.add(_maxGas.mul(_gasPriceBid));\n require(msg.value >= expectedEth, \"WRONG_ETH_VALUE\");\n }\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // transfer tokens to escrow\n IERC20(_l1Token).transferFrom(from, address(this), _amount);\n\n emit FakeTxToL2(from, msg.value, _maxGas, _gasPriceBid, maxSubmissionCost, outboundCalldata);\n }\n }\n emit DepositInitiated(_l1Token, from, _to, seqNum, _amount);\n\n return abi.encode(seqNum);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L2\n * Actually does nothing, just keeping it here as its useful to define the expected\n * calldata for the outgoing transfer in tests.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recepient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {}\n\n /**\n * @notice Creates calldata required to create a retryable ticket\n * @dev encodes the target function with its params which\n * will be called on L2 when the retryable ticket is redeemed\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L1 from which we're transferring tokens\n * @param _to Address on L2 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L2 transaction, which must be empty unless the caller is whitelisted\n * @return Encoded calldata (including function selector) for the L2 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n bytes memory emptyBytes;\n\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(emptyBytes, _data)\n );\n }\n\n /**\n * @notice Decodes calldata required for transfer of tokens to L2\n * @dev Data must include maxSubmissionCost, extraData can be left empty. When the router\n * sends an outbound message, data also contains the from address, but this mock\n * doesn't consider this case\n * @param _data Encoded callhook data containing maxSubmissionCost and extraData\n * @return Sender of the tx\n * @return Max ether value used to submit the retryable ticket\n * @return Additional data sent to L2\n */\n function _parseOutboundData(bytes memory _data) private view returns (address, uint256, bytes memory) {\n address from;\n uint256 maxSubmissionCost;\n bytes memory extraData;\n from = msg.sender;\n // User-encoded data contains the max retryable ticket submission cost\n // and additional L2 calldata\n (maxSubmissionCost, extraData) = abi.decode(_data, (uint256, bytes));\n return (from, maxSubmissionCost, extraData);\n }\n}\n" + }, + "contracts/tests/L2TokenGatewayMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\n\nimport { Ownable } from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport { ITokenGateway } from \"../arbitrum//ITokenGateway.sol\";\nimport { GraphTokenMock } from \"./GraphTokenMock.sol\";\nimport { ICallhookReceiver } from \"../ICallhookReceiver.sol\";\n\n/**\n * @title L2 Token Gateway mock contract\n * @dev Used for testing purposes, DO NOT USE IN PRODUCTION\n */\ncontract L2TokenGatewayMock is Ownable {\n /// Address of the L1 GRT contract\n address public immutable l1Token;\n /// Address of the L2 GRT contract\n address public immutable l2Token;\n /// Next ID to return when sending an outboundTransfer\n uint256 public nextId;\n\n /// @dev Emitted when a (fake) transaction to L1 is created\n event FakeTxToL1(address from, bytes outboundCalldata);\n /// @dev Emitted when a (fake) retryable ticket is received from L1\n event DepositFinalized(address token, address indexed from, address indexed to, uint256 amount);\n\n /// @dev Emitted when an outbound transfer is initiated, i.e. tokens are withdrawn to L1 from L2\n event WithdrawalInitiated(\n address l1Token,\n address indexed from,\n address indexed to,\n uint256 indexed sequenceNumber,\n uint256 amount\n );\n\n /**\n * @notice L2 Token Gateway Contract Constructor.\n * @param _l1Token Address of the L1 GRT contract\n * @param _l2Token Address of the L2 GRT contract\n */\n constructor(address _l1Token, address _l2Token) {\n l1Token = _l1Token;\n l2Token = _l2Token;\n }\n\n /**\n * @notice Creates and sends a (fake) transfer of GRT to L1.\n * This mock will actually just emit an event with parameters equivalent to what the real L2GraphTokenGateway\n * would send to L1.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _to Recipient address on L2\n * @param _amount Amount of tokens to tranfer\n * @param _data Encoded maxSubmissionCost and sender address along with additional calldata\n * @return ID of the L2-L1 message (incrementing on every call)\n */\n function outboundTransfer(\n address _l1Token,\n address _to,\n uint256 _amount,\n uint256,\n uint256,\n bytes calldata _data\n ) external payable returns (bytes memory) {\n require(_l1Token == l1Token, \"INVALID_L1_TOKEN\");\n require(_amount > 0, \"INVALID_ZERO_AMOUNT\");\n require(_to != address(0), \"INVALID_DESTINATION\");\n\n // nested scopes to avoid stack too deep errors\n address from;\n uint256 id = nextId;\n nextId += 1;\n {\n bytes memory outboundCalldata;\n {\n bytes memory extraData;\n (from, extraData) = _parseOutboundData(_data);\n\n require(msg.value == 0, \"!value\");\n require(extraData.length == 0, \"!extraData\");\n outboundCalldata = getOutboundCalldata(_l1Token, from, _to, _amount, extraData);\n }\n {\n // burn tokens from the sender, they will be released from escrow in L1\n GraphTokenMock(l2Token).bridgeBurn(from, _amount);\n\n emit FakeTxToL1(from, outboundCalldata);\n }\n }\n emit WithdrawalInitiated(_l1Token, from, _to, id, _amount);\n\n return abi.encode(id);\n }\n\n /**\n * @notice (Mock) Receives withdrawn tokens from L1\n * Implements calling callhooks if data is non-empty.\n * @param _l1Token L1 Address of the GRT contract (needed for compatibility with Arbitrum Gateway Router)\n * @param _from Address of the sender\n * @param _to Recipient address on L1\n * @param _amount Amount of tokens transferred\n * @param _data Additional calldata, will trigger an onTokenTransfer call if non-empty\n */\n function finalizeInboundTransfer(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes calldata _data\n ) external payable {\n require(_l1Token == l1Token, \"TOKEN_NOT_GRT\");\n require(msg.value == 0, \"INVALID_NONZERO_VALUE\");\n\n GraphTokenMock(l2Token).bridgeMint(_to, _amount);\n\n if (_data.length > 0) {\n ICallhookReceiver(_to).onTokenTransfer(_from, _amount, _data);\n }\n\n emit DepositFinalized(_l1Token, _from, _to, _amount);\n }\n\n /**\n * @notice Calculate the L2 address of a bridged token\n * @dev In our case, this would only work for GRT.\n * @param l1ERC20 address of L1 GRT contract\n * @return L2 address of the bridged GRT token\n */\n function calculateL2TokenAddress(address l1ERC20) public view returns (address) {\n if (l1ERC20 != l1Token) {\n return address(0);\n }\n return l2Token;\n }\n\n /**\n * @notice Creates calldata required to create a tx to L1\n * @param _l1Token Address of the Graph token contract on L1\n * @param _from Address on L2 from which we're transferring tokens\n * @param _to Address on L1 to which we're transferring tokens\n * @param _amount Amount of GRT to transfer\n * @param _data Additional call data for the L1 transaction, which must be empty\n * @return Encoded calldata (including function selector) for the L1 transaction\n */\n function getOutboundCalldata(\n address _l1Token,\n address _from,\n address _to,\n uint256 _amount,\n bytes memory _data\n ) public pure returns (bytes memory) {\n return\n abi.encodeWithSelector(\n ITokenGateway.finalizeInboundTransfer.selector,\n _l1Token,\n _from,\n _to,\n _amount,\n abi.encode(0, _data)\n );\n }\n\n /**\n * @dev Decodes calldata required for transfer of tokens to L1.\n * extraData can be left empty\n * @param _data Encoded callhook data\n * @return Sender of the tx\n * @return Any other data sent to L1\n */\n function _parseOutboundData(bytes calldata _data) private view returns (address, bytes memory) {\n address from;\n bytes memory extraData;\n // The mock doesn't take messages from the Router\n from = msg.sender;\n extraData = _data;\n return (from, extraData);\n }\n}\n" + }, + "contracts/tests/Stakes.sol": { + "content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n/**\n * @title A collection of data structures and functions to manage the Indexer Stake state.\n * Used for low-level state changes, require() conditions should be evaluated\n * at the caller function scope.\n */\nlibrary Stakes {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n struct Indexer {\n uint256 tokensStaked; // Tokens on the indexer stake (staked by the indexer)\n uint256 tokensAllocated; // Tokens used in allocations\n uint256 tokensLocked; // Tokens locked for withdrawal subject to thawing period\n uint256 tokensLockedUntil; // Block when locked tokens can be withdrawn\n }\n\n /**\n * @dev Deposit tokens to the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to deposit\n */\n function deposit(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.add(_tokens);\n }\n\n /**\n * @dev Release tokens from the indexer stake.\n * @param stake Stake data\n * @param _tokens Amount of tokens to release\n */\n function release(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensStaked = stake.tokensStaked.sub(_tokens);\n }\n\n /**\n * @dev Allocate tokens from the main stack to a SubgraphDeployment.\n * @param stake Stake data\n * @param _tokens Amount of tokens to allocate\n */\n function allocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.add(_tokens);\n }\n\n /**\n * @dev Unallocate tokens from a SubgraphDeployment back to the main stack.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unallocate\n */\n function unallocate(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensAllocated = stake.tokensAllocated.sub(_tokens);\n }\n\n /**\n * @dev Lock tokens until a thawing period pass.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _period Period in blocks that need to pass before withdrawal\n */\n function lockTokens(Stakes.Indexer storage stake, uint256 _tokens, uint256 _period) internal {\n // Take into account period averaging for multiple unstake requests\n uint256 lockingPeriod = _period;\n if (stake.tokensLocked > 0) {\n lockingPeriod = stake.getLockingPeriod(_tokens, _period);\n }\n\n // Update balances\n stake.tokensLocked = stake.tokensLocked.add(_tokens);\n stake.tokensLockedUntil = block.number.add(lockingPeriod);\n }\n\n /**\n * @dev Unlock tokens.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unkock\n */\n function unlockTokens(Stakes.Indexer storage stake, uint256 _tokens) internal {\n stake.tokensLocked = stake.tokensLocked.sub(_tokens);\n if (stake.tokensLocked == 0) {\n stake.tokensLockedUntil = 0;\n }\n }\n\n /**\n * @dev Take all tokens out from the locked stake for withdrawal.\n * @param stake Stake data\n * @return Amount of tokens being withdrawn\n */\n function withdrawTokens(Stakes.Indexer storage stake) internal returns (uint256) {\n // Calculate tokens that can be released\n uint256 tokensToWithdraw = stake.tokensWithdrawable();\n\n if (tokensToWithdraw > 0) {\n // Reset locked tokens\n stake.unlockTokens(tokensToWithdraw);\n\n // Decrease indexer stake\n stake.release(tokensToWithdraw);\n }\n\n return tokensToWithdraw;\n }\n\n /**\n * @dev Get the locking period of the tokens to unstake.\n * If already unstaked before calculate the weighted average.\n * @param stake Stake data\n * @param _tokens Amount of tokens to unstake\n * @param _thawingPeriod Period in blocks that need to pass before withdrawal\n * @return True if staked\n */\n function getLockingPeriod(\n Stakes.Indexer memory stake,\n uint256 _tokens,\n uint256 _thawingPeriod\n ) internal view returns (uint256) {\n uint256 blockNum = block.number;\n uint256 periodA = (stake.tokensLockedUntil > blockNum) ? stake.tokensLockedUntil.sub(blockNum) : 0;\n uint256 periodB = _thawingPeriod;\n uint256 stakeA = stake.tokensLocked;\n uint256 stakeB = _tokens;\n return periodA.mul(stakeA).add(periodB.mul(stakeB)).div(stakeA.add(stakeB));\n }\n\n /**\n * @dev Return true if there are tokens staked by the Indexer.\n * @param stake Stake data\n * @return True if staked\n */\n function hasTokens(Stakes.Indexer memory stake) internal pure returns (bool) {\n return stake.tokensStaked > 0;\n }\n\n /**\n * @dev Return the amount of tokens used in allocations and locked for withdrawal.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensUsed(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAllocated.add(stake.tokensLocked);\n }\n\n /**\n * @dev Return the amount of tokens staked not considering the ones that are already going\n * through the thawing period or are ready for withdrawal. We call it secure stake because\n * it is not subject to change by a withdraw call from the indexer.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensSecureStake(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensStaked.sub(stake.tokensLocked);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for any purpose.\n * Any token that is allocated cannot be used as well as tokens that are going through the\n * thawing period or are withdrawable\n * Calc: tokensStaked - tokensAllocated - tokensLocked\n * @param stake Stake data\n * @return Token amount\n */\n function tokensAvailable(Stakes.Indexer memory stake) internal pure returns (uint256) {\n return stake.tokensAvailableWithDelegation(0);\n }\n\n /**\n * @dev Tokens free balance on the indexer stake that can be used for allocations.\n * This function accepts a parameter for extra delegated capacity that takes into\n * account delegated tokens\n * @param stake Stake data\n * @param _delegatedCapacity Amount of tokens used from delegators to calculate availability\n * @return Token amount\n */\n function tokensAvailableWithDelegation(\n Stakes.Indexer memory stake,\n uint256 _delegatedCapacity\n ) internal pure returns (uint256) {\n uint256 tokensCapacity = stake.tokensStaked.add(_delegatedCapacity);\n uint256 _tokensUsed = stake.tokensUsed();\n // If more tokens are used than the current capacity, the indexer is overallocated.\n // This means the indexer doesn't have available capacity to create new allocations.\n // We can reach this state when the indexer has funds allocated and then any\n // of these conditions happen:\n // - The delegationCapacity ratio is reduced.\n // - The indexer stake is slashed.\n // - A delegator removes enough stake.\n if (_tokensUsed > tokensCapacity) {\n // Indexer stake is over allocated: return 0 to avoid stake to be used until\n // the overallocation is restored by staking more tokens, unallocating tokens\n // or using more delegated funds\n return 0;\n }\n return tokensCapacity.sub(_tokensUsed);\n }\n\n /**\n * @dev Tokens available for withdrawal after thawing period.\n * @param stake Stake data\n * @return Token amount\n */\n function tokensWithdrawable(Stakes.Indexer memory stake) internal view returns (uint256) {\n // No tokens to withdraw before locking period\n if (stake.tokensLockedUntil == 0 || block.number < stake.tokensLockedUntil) {\n return 0;\n }\n return stake.tokensLocked;\n }\n}\n" + }, + "contracts/tests/StakingMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./Stakes.sol\";\n\ncontract StakingMock {\n using SafeMath for uint256;\n using Stakes for Stakes.Indexer;\n\n // -- State --\n\n uint256 public minimumIndexerStake = 100e18;\n uint256 public thawingPeriod = 10; // 10 blocks\n IERC20 public token;\n\n // Indexer stakes : indexer => Stake\n mapping(address => Stakes.Indexer) public stakes;\n\n /**\n * @dev Emitted when `indexer` stake `tokens` amount.\n */\n event StakeDeposited(address indexed indexer, uint256 tokens);\n\n /**\n * @dev Emitted when `indexer` unstaked and locked `tokens` amount `until` block.\n */\n event StakeLocked(address indexed indexer, uint256 tokens, uint256 until);\n\n /**\n * @dev Emitted when `indexer` withdrew `tokens` staked.\n */\n event StakeWithdrawn(address indexed indexer, uint256 tokens);\n\n // Contract constructor.\n constructor(IERC20 _token) {\n require(address(_token) != address(0), \"!token\");\n token = _token;\n }\n\n receive() external payable {}\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _tokens Amount of tokens to stake\n */\n function stake(uint256 _tokens) external {\n stakeTo(msg.sender, _tokens);\n }\n\n /**\n * @dev Deposit tokens on the indexer stake.\n * @param _indexer Address of the indexer\n * @param _tokens Amount of tokens to stake\n */\n function stakeTo(address _indexer, uint256 _tokens) public {\n require(_tokens > 0, \"!tokens\");\n\n // Ensure minimum stake\n require(stakes[_indexer].tokensSecureStake().add(_tokens) >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Transfer tokens to stake from caller to this contract\n require(token.transferFrom(msg.sender, address(this), _tokens), \"!transfer\");\n\n // Stake the transferred tokens\n _stake(_indexer, _tokens);\n }\n\n /**\n * @dev Unstake tokens from the indexer stake, lock them until thawing period expires.\n * @param _tokens Amount of tokens to unstake\n */\n function unstake(uint256 _tokens) external {\n address indexer = msg.sender;\n Stakes.Indexer storage indexerStake = stakes[indexer];\n\n require(_tokens > 0, \"!tokens\");\n require(indexerStake.hasTokens(), \"!stake\");\n require(indexerStake.tokensAvailable() >= _tokens, \"!stake-avail\");\n\n // Ensure minimum stake\n uint256 newStake = indexerStake.tokensSecureStake().sub(_tokens);\n require(newStake == 0 || newStake >= minimumIndexerStake, \"!minimumIndexerStake\");\n\n // Before locking more tokens, withdraw any unlocked ones\n uint256 tokensToWithdraw = indexerStake.tokensWithdrawable();\n if (tokensToWithdraw > 0) {\n _withdraw(indexer);\n }\n\n indexerStake.lockTokens(_tokens, thawingPeriod);\n\n emit StakeLocked(indexer, indexerStake.tokensLocked, indexerStake.tokensLockedUntil);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n */\n function withdraw() external {\n _withdraw(msg.sender);\n }\n\n function _stake(address _indexer, uint256 _tokens) internal {\n // Deposit tokens into the indexer stake\n Stakes.Indexer storage indexerStake = stakes[_indexer];\n indexerStake.deposit(_tokens);\n\n emit StakeDeposited(_indexer, _tokens);\n }\n\n /**\n * @dev Withdraw indexer tokens once the thawing period has passed.\n * @param _indexer Address of indexer to withdraw funds from\n */\n function _withdraw(address _indexer) private {\n // Get tokens available for withdraw and update balance\n uint256 tokensToWithdraw = stakes[_indexer].withdrawTokens();\n require(tokensToWithdraw > 0, \"!tokens\");\n\n // Return tokens to the indexer\n require(token.transfer(_indexer, tokensToWithdraw), \"!transfer\");\n\n emit StakeWithdrawn(_indexer, tokensToWithdraw);\n }\n}\n" + }, + "contracts/tests/WalletMock.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.7.3;\npragma experimental ABIEncoderV2;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title WalletMock: a mock wallet contract for testing purposes\n * @dev For testing only, DO NOT USE IN PRODUCTION.\n * This is used to test L1-L2 transfer tools and to create scenarios\n * where an invalid wallet calls the transfer tool, e.g. a wallet that has an invalid\n * manager, or a wallet that has not been initialized.\n */\ncontract WalletMock {\n /// Target contract for the fallback function (usually a transfer tool contract)\n address public immutable target;\n /// Address of the GRT (mock) token\n address public immutable token;\n /// Address of the wallet's manager\n address public immutable manager;\n /// Whether the wallet has been initialized\n bool public immutable isInitialized;\n /// Whether the beneficiary has accepted the lock\n bool public immutable isAccepted;\n\n /**\n * @notice WalletMock constructor\n * @dev This constructor sets all the state variables so that\n * specific test scenarios can be created just by deploying this contract.\n * @param _target Target contract for the fallback function\n * @param _token Address of the GRT (mock) token\n * @param _manager Address of the wallet's manager\n * @param _isInitialized Whether the wallet has been initialized\n * @param _isAccepted Whether the beneficiary has accepted the lock\n */\n constructor(address _target, address _token, address _manager, bool _isInitialized, bool _isAccepted) {\n target = _target;\n token = _token;\n manager = _manager;\n isInitialized = _isInitialized;\n isAccepted = _isAccepted;\n }\n\n /**\n * @notice Fallback function\n * @dev This function calls the target contract with the data sent to this contract.\n * This is used to test the L1-L2 transfer tool.\n */\n fallback() external payable {\n // Call function with data\n Address.functionCall(target, msg.data);\n }\n\n /**\n * @notice Receive function\n * @dev This function is added to avoid compiler warnings, but just reverts.\n */\n receive() external payable {\n revert(\"Invalid call\");\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/packages/token-distribution/eslint.config.js b/packages/token-distribution/eslint.config.js new file mode 100644 index 000000000..ed2d51271 --- /dev/null +++ b/packages/token-distribution/eslint.config.js @@ -0,0 +1,14 @@ +const config = require('eslint-graph-config') + +module.exports = [ + ...config.default, + { + rules: { + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-unsafe-argument': 'off', + }, + }, +] diff --git a/packages/token-distribution/hardhat.config.ts b/packages/token-distribution/hardhat.config.ts new file mode 100644 index 000000000..eaa994346 --- /dev/null +++ b/packages/token-distribution/hardhat.config.ts @@ -0,0 +1,192 @@ +import * as dotenv from 'dotenv' +import { extendEnvironment, task } from 'hardhat/config' + +dotenv.config() + +// Plugins + +import '@nomiclabs/hardhat-ethers' +import '@nomiclabs/hardhat-etherscan' +import '@nomiclabs/hardhat-waffle' +import 'hardhat-deploy' +import 'hardhat-abi-exporter' +import '@typechain/hardhat' +import 'hardhat-gas-reporter' +import '@openzeppelin/hardhat-upgrades' + +// Tasks + +import './ops/create' +import './ops/delete' +import './ops/info' +import './ops/manager' +import './ops/beneficiary' + +// Networks + +interface NetworkConfig { + network: string + chainId: number + url?: string + gas?: number | 'auto' + gasPrice?: number | 'auto' +} + +const networkConfigs: NetworkConfig[] = [ + { network: 'mainnet', chainId: 1 }, + { network: 'ropsten', chainId: 3 }, + { network: 'rinkeby', chainId: 4 }, + { network: 'goerli', chainId: 5 }, + { network: 'kovan', chainId: 42 }, + { network: 'sepolia', chainId: 11155111 }, + { + network: 'arbitrum-one', + chainId: 42161, + url: 'https://arb1.arbitrum.io/rpc', + }, + { + network: 'arbitrum-goerli', + chainId: 421613, + url: 'https://goerli-rollup.arbitrum.io/rpc', + }, + { + network: 'arbitrum-sepolia', + chainId: 421614, + url: 'https://sepolia-rollup.arbitrum.io/rpcblock', + }, +] + +function getAccountMnemonic() { + return process.env.MNEMONIC || '' +} + +function getDefaultProviderURL(network: string) { + return `https://${network}.infura.io/v3/${process.env.INFURA_KEY}` +} + +function setupNetworkConfig(config) { + for (const netConfig of networkConfigs) { + config.networks[netConfig.network] = { + chainId: netConfig.chainId, + url: netConfig.url ? netConfig.url : getDefaultProviderURL(netConfig.network), + gas: netConfig.gas || 'auto', + gasPrice: netConfig.gasPrice || 'auto', + accounts: { + mnemonic: getAccountMnemonic(), + }, + } + } +} + +// Env + +// eslint-disable-next-line @typescript-eslint/no-misused-promises +extendEnvironment(async (hre) => { + const accounts = await hre.ethers.getSigners() + try { + const deployment = await hre.deployments.get('GraphTokenLockManager') + const contract = await hre.ethers.getContractAt('GraphTokenLockManager', deployment.address) + await contract.deployed() // test if deployed + + hre['c'] = { + GraphTokenLockManager: contract.connect(accounts[0]), + } + } catch (err) { + // do not load the contract + } +}) + +// Tasks + +task('accounts', 'Prints the list of accounts', async (taskArgs, hre) => { + const accounts = await hre.ethers.getSigners() + for (const account of accounts) { + console.log(await account.getAddress()) + } +}) + +// Config + +const config = { + paths: { + sources: './contracts', + tests: './test', + cache: './cache', + artifacts: './build/artifacts', + }, + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + solidity: { + compilers: [ + { + version: '0.7.3', + settings: { + optimizer: { + enabled: false, + runs: 200, + }, + }, + }, + ], + }, + defaultNetwork: 'hardhat', + networks: { + hardhat: { + chainId: 1337, + loggingEnabled: false, + gas: 12000000, + gasPrice: 'auto', + blockGasLimit: 12000000, + }, + ganache: { + chainId: 1337, + url: 'http://localhost:8545', + }, + }, + namedAccounts: { + deployer: { + default: 0, + }, + }, + etherscan: { + apiKey: process.env.ETHERSCAN_API_KEY, + customChains: [ + { + network: 'arbitrum-sepolia', + chainId: 421614, + urls: { + apiURL: 'https://api-sepolia.arbiscan.io/api', + browserURL: 'https://sepolia.arbiscan.io', + }, + }, + ], + }, + typechain: { + outDir: 'build/typechain/contracts', + target: 'ethers-v5', + }, + abiExporter: { + path: './build/abis', + clear: false, + flat: true, + runOnCompile: true, + }, + contractSizer: { + alphaSort: true, + runOnCompile: false, + }, + gasReporter: { + enabled: process.env.REPORT_GAS ? true : false, + showTimeSpent: true, + currency: 'USD', + outputFile: 'reports/gas-report.log', + }, +} + +setupNetworkConfig(config) + +export default config diff --git a/packages/token-distribution/ops/beneficiary.ts b/packages/token-distribution/ops/beneficiary.ts new file mode 100644 index 000000000..547c5db7a --- /dev/null +++ b/packages/token-distribution/ops/beneficiary.ts @@ -0,0 +1,78 @@ +import { task } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { askConfirm, waitTransaction } from './create' +import consola from 'consola' + +const logger = consola.create({}) + +task('beneficiary-accept-lock', 'Accept token lock. Only callable by beneficiary') + .addParam('contract', 'Address of the vesting contract') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + const { deployer } = await hre.getNamedAccounts() + + const vestingContract = await hre.ethers.getContractAt('GraphTokenLockWallet', taskArgs.contract) + const beneficiary = await vestingContract.beneficiary() + let isAccepted = await vestingContract.isAccepted() + + logger.info(`Vesting contract address: ${vestingContract.address}}`) + logger.info(`Beneficiary: ${beneficiary}`) + logger.info(`Connected account: ${deployer}`) + logger.info(`Lock accepted: ${isAccepted}`) + + // Check lock status + if (isAccepted) { + logger.warn('Lock already accepted, exiting...') + process.exit(0) + } + + // Check beneficiary + if (beneficiary !== deployer) { + logger.error('Only the beneficiary can accept the vesting contract lock!') + process.exit(1) + } + + // Confirm + logger.info('Preparing transaction to accept token lock...') + if (!(await askConfirm())) { + logger.log('Cancelled') + process.exit(1) + } + + // Accept lock + const tx = await vestingContract.acceptLock() + await waitTransaction(tx) + + // Verify lock state + isAccepted = await vestingContract.isAccepted() + if (isAccepted) { + logger.info(`Lock accepted successfully!`) + } else { + logger.error(`Lock not accepted! Unknown error, please try again`) + } + }) + +task('beneficiary-vesting-info', 'Print vesting contract info') + .addParam('contract', 'Address of the vesting contract') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + const vestingContract = await hre.ethers.getContractAt('GraphTokenLockWallet', taskArgs.contract) + const beneficiary = await vestingContract.beneficiary() + const isAccepted = await vestingContract.isAccepted() + const startTime = await vestingContract.startTime() + const endTime = await vestingContract.endTime() + const periods = await vestingContract.periods() + const releaseStartTime = await vestingContract.releaseStartTime() + const vestingCliffTime = await vestingContract.vestingCliffTime() + const managedAmount = await vestingContract.managedAmount() + const revocable = await vestingContract.revocable() + + logger.info(`Vesting contract address: ${vestingContract.address}}`) + logger.info(`Beneficiary: ${beneficiary}`) + logger.info(`Managed amount: ${managedAmount}`) + logger.info(`Lock accepted: ${isAccepted}`) + logger.info(`Revocable: ${revocable}`) + logger.info(`Start time: ${startTime}`) + logger.info(`End time: ${endTime}`) + logger.info(`Periods: ${periods}`) + logger.info(`Release start time: ${releaseStartTime}`) + logger.info(`Vesting cliff time: ${vestingCliffTime}`) + }) diff --git a/packages/token-distribution/ops/create.ts b/packages/token-distribution/ops/create.ts new file mode 100644 index 000000000..0dce2d253 --- /dev/null +++ b/packages/token-distribution/ops/create.ts @@ -0,0 +1,580 @@ +import PQueue from 'p-queue' +import fs from 'fs' +import consola from 'consola' +import inquirer from 'inquirer' +import { BigNumber, Contract, ContractFactory, ContractReceipt, ContractTransaction, Event, utils } from 'ethers' + +import { NonceManager } from '@ethersproject/experimental' +import { task } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { boolean } from 'hardhat/internal/core/params/argumentTypes' +import { TxBuilder } from './tx-builder' + +const { getAddress, keccak256, formatEther, parseEther } = utils + +const logger = consola.create({}) + +enum Revocability { + NotSet, + Enabled, + Disabled, +} + +interface TokenLockConfigEntry { + owner?: string + beneficiary: string + managedAmount: BigNumber + startTime: string + endTime: string + periods: string + revocable: Revocability + releaseStartTime: string + vestingCliffTime: string + salt?: string + txHash?: string + contractAddress?: string +} + +interface TokenLockDeployEntry extends TokenLockConfigEntry { + contractAddress: string + salt: string + txHash: string +} + +export const askConfirm = async () => { + const res = await inquirer.prompt({ + name: 'confirm', + type: 'confirm', + message: `Are you sure you want to proceed?`, + }) + return res.confirm ? res.confirm as boolean : false +} + +const isValidAddress = (address: string) => { + try { + getAddress(address) + return true + } catch (err) { + logger.error(`Invalid address ${address}`) + return false + } +} + +export const isValidAddressOrFail = (address: string) => { + if (!isValidAddress(address)) { + process.exit(1) + } +} + +const loadDeployData = (filepath: string): TokenLockConfigEntry[] => { + const data = fs.readFileSync(filepath, 'utf8') + const entries = data.split('\n').map(e => e.trim()) + entries.shift() // remove the title from the csv + return entries + .filter(entryData => !!entryData) + .map((entryData) => { + const entry = entryData.split(',') + return { + beneficiary: entry[0], + managedAmount: parseEther(entry[1]), + startTime: entry[2], + endTime: entry[3], + periods: entry[4], + revocable: parseInt(entry[5]), + releaseStartTime: entry[6], + vestingCliffTime: entry[7], + } + }) +} + +const loadResultData = (filepath: string): TokenLockConfigEntry[] => { + const data = fs.readFileSync(filepath, 'utf8') + const entries = data.split('\n').map(e => e.trim()) + return entries + .filter(entryData => !!entryData) + .map((entryData) => { + const entry = entryData.split(',') + return { + beneficiary: entry[0], + managedAmount: parseEther(entry[1]), + startTime: entry[2], + endTime: entry[3], + periods: entry[4], + revocable: parseInt(entry[5]), + releaseStartTime: entry[6], + vestingCliffTime: entry[7], + contractAddress: entry[8], + salt: entry[9], + txHash: entry[10], + } + }) +} + +const deployEntryToCSV = (entry: TokenLockDeployEntry) => { + return [ + entry.beneficiary, + formatEther(entry.managedAmount), + entry.startTime, + entry.endTime, + entry.periods, + entry.revocable, + entry.releaseStartTime, + entry.vestingCliffTime, + entry.contractAddress, + entry.salt, + entry.txHash, + ].join(',') +} + +const saveDeployResult = (filepath: string, entry: TokenLockDeployEntry) => { + const line = deployEntryToCSV(entry) + '\n' + fs.writeFileSync(filepath, line, { + flag: 'a+', + }) +} + +const checkAddresses = (entries: TokenLockConfigEntry[]): boolean => { + for (const entry of entries) { + if (!isValidAddress(entry.beneficiary)) { + return false + } + } + return true +} + +const getTotalAmount = (entries: TokenLockConfigEntry[]): BigNumber => { + return entries.reduce((total, entry) => total.add(entry.managedAmount), BigNumber.from(0)) +} + +const prettyDate = (date: string) => { + const n = parseInt(date) + if (n === 0) return '0' + const d = new Date(n * 1000) + return d.toLocaleString() +} + +const prettyConfigEntry = (config: TokenLockConfigEntry) => { + return ` + Beneficiary: ${config.beneficiary} + Amount: ${formatEther(config.managedAmount)} GRT + Starts: ${config.startTime} (${prettyDate(config.startTime)}) + Ends: ${config.endTime} (${prettyDate(config.endTime)}) + Periods: ${config.periods} + Revocable: ${config.revocable} + ReleaseCliff: ${config.releaseStartTime} (${prettyDate(config.releaseStartTime)}) + VestingCliff: ${config.vestingCliffTime} (${prettyDate(config.vestingCliffTime)}) + Owner: ${config.owner} + -> ContractAddress: ${config.contractAddress} + ` +} + +export const prettyEnv = async (hre: HardhatRuntimeEnvironment) => { + const { deployer } = await hre.getNamedAccounts() + + const provider = hre.ethers.provider + + const balance = await provider.getBalance(deployer) + const chainId = (await provider.getNetwork()).chainId + const nonce = await provider.getTransactionCount(deployer) + + const gas = hre.network.config.gas + const gasPrice = hre.network.config.gasPrice + + return ` + Wallet: address=${deployer} chain=${chainId} nonce=${nonce} balance=${formatEther(balance)} + Gas settings: gas=${gas} gasPrice=${gasPrice} + ` +} + +const calculateSalt = async ( + hre: HardhatRuntimeEnvironment, + entry: TokenLockConfigEntry, + managerAddress: string, + tokenAddress: string, +) => { + const factory = await getContractFactory(hre, 'GraphTokenLockWallet') + + return keccak256( + factory.interface.encodeFunctionData( + 'initialize(address,address,address,address,uint256,uint256,uint256,uint256,uint256,uint256,uint8)', + [ + managerAddress, + entry.owner, + entry.beneficiary, + tokenAddress, + entry.managedAmount, + entry.startTime, + entry.endTime, + entry.periods, + entry.releaseStartTime, + entry.vestingCliffTime, + entry.revocable, + ], + ), + ) +} + +const getContractFactory = async (hre: HardhatRuntimeEnvironment, name: string) => { + const artifact = await hre.deployments.getArtifact(name) + return new ContractFactory(artifact.abi, artifact.bytecode) +} + +const getDeployContractAddresses = async (entries: TokenLockConfigEntry[], manager: Contract) => { + const masterCopy = await manager.masterCopy() + for (const entry of entries) { + // There are two type of managers + let contractAddress = '' + try { + contractAddress = await manager['getDeploymentAddress(bytes32,address,address)']( + entry.salt, + masterCopy, + manager.address, + ) + } catch (error) { + contractAddress = await manager['getDeploymentAddress(bytes32,address)'](entry.salt, masterCopy) + } + + const deployEntry = { ...entry, salt: entry.salt, txHash: '', contractAddress } + logger.log(prettyConfigEntry(deployEntry)) + } +} + +const populateEntries = async ( + hre: HardhatRuntimeEnvironment, + entries: TokenLockConfigEntry[], + managerAddress: string, + tokenAddress: string, + ownerAddress: string, +) => { + const results: TokenLockConfigEntry[] = [] + for (const entry of entries) { + entry.owner = ownerAddress + entry.salt = await calculateSalt(hre, entry, managerAddress, tokenAddress) + results.push(entry) + } + return results +} + +export const getTokenLockManagerOrFail = async (hre: HardhatRuntimeEnvironment, name: string) => { + const deployment = await hre.deployments.get(name) + if (!deployment.address) { + logger.error('GraphTokenLockManager address not found') + process.exit(1) + } + + const manager = await hre.ethers.getContractAt('GraphTokenLockManager', deployment.address) + try { + await manager.deployed() + } catch (err) { + logger.error('GraphTokenLockManager not deployed at', manager.address) + process.exit(1) + } + + return manager +} + +export const waitTransaction = async (tx: ContractTransaction, confirmations = 1): Promise => { + logger.log(`> Transaction sent: ${tx.hash}`) + const receipt = await tx.wait(confirmations) + receipt.status ? logger.success(`Transaction succeeded: ${tx.hash}`) : logger.warn(`Transaction failed: ${tx.hash}`) + return receipt +} + +// -- Tasks -- + +task('create-token-locks', 'Create token lock contracts from file') + .addParam('deployFile', 'File from where to read the deploy config') + .addParam('resultFile', 'File where to save results') + .addParam('ownerAddress', 'Owner address of token lock contracts') + .addParam('managerName', 'Name of the token lock manager deployment', 'GraphTokenLockManager') + .addFlag('dryRun', 'Get the deterministic contract addresses but do not deploy') + .addFlag( + 'txBuilder', + 'Output transaction batch in JSON format, compatible with Gnosis Safe transaction builder. Does not deploy contracts', + ) + .addOptionalParam('txBuilderTemplate', 'File to use as a template for the transaction builder') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Get contracts + const manager = await getTokenLockManagerOrFail(hre, taskArgs.managerName) + + // Prepare + logger.log(await prettyEnv(hre)) + + const tokenAddress = await manager.token() + + logger.info('Deploying token lock contracts...') + logger.log(`> GraphToken: ${tokenAddress}`) + logger.log(`> GraphTokenLockMasterCopy: ${await manager.masterCopy()}`) + logger.log(`> GraphTokenLockManager: ${manager.address}`) + + // Load config entries + logger.log('') + logger.info('Verifying deployment data...') + let entries = loadDeployData(taskArgs.deployFile) + if (!checkAddresses(entries)) { + process.exit(1) + } + logger.success(`Total of ${entries.length} entries. All good!`) + + // Load deployed entries + const deployedEntries = loadResultData(taskArgs.resultFile) + + // Populate entries + entries = await populateEntries(hre, entries, manager.address, tokenAddress, taskArgs.ownerAddress) + + // Filter out already deployed ones + entries = entries.filter(entry => !deployedEntries.find(deployedEntry => deployedEntry.salt === entry.salt)) + logger.success(`Total of ${entries.length} entries after removing already deployed. All good!`) + if (entries.length === 0) { + logger.warn('Nothing new to deploy') + process.exit(1) + } + + // Dry running + if (taskArgs.dryRun) { + logger.info('Running in dry run mode!') + await getDeployContractAddresses(entries, manager) + process.exit(0) + } + + // If deploying contracts, check + // - deployer is the manager owner + // - deployer is well funded + if (!taskArgs.txBuilder) { + // Ensure deployer is the manager owner + const tokenLockManagerOwner = await manager.owner() + const { deployer } = await hre.getNamedAccounts() + if (tokenLockManagerOwner !== deployer) { + logger.error('Only the owner can deploy token locks') + process.exit(1) + } + + // Check if Manager is funded + logger.log('') + logger.info('Verifying balances...') + const grt = await hre.ethers.getContractAt('ERC20', tokenAddress) + const totalAmount = getTotalAmount(entries) + const currentBalance = await grt.balanceOf(manager.address) + logger.log(`> Amount to distribute: ${formatEther(totalAmount)} GRT`) + logger.log(`> Amount in the Manager: ${formatEther(currentBalance)} GRT`) + if (currentBalance.lt(totalAmount)) { + logger.error(`GraphTokenLockManager is underfunded. Deposit more funds into ${manager.address}`) + process.exit(1) + } + logger.success('Manager has enough tokens to fund contracts') + } + + // Summary + if (!(await askConfirm())) { + logger.log('Cancelled') + process.exit(1) + } + + if (!taskArgs.txBuilder) { + // Deploy contracts + const accounts = await hre.ethers.getSigners() + const nonceManager = new NonceManager(accounts[0]) // Use NonceManager to send concurrent txs + + const queue = new PQueue({ concurrency: 6 }) + + for (const entry of entries) { + await queue.add(async () => { + logger.log('') + logger.info(`Creating contract...`) + logger.log(prettyConfigEntry(entry)) + + try { + // Deploy + const tx = await manager + .connect(nonceManager) + .createTokenLockWallet( + entry.owner, + entry.beneficiary, + entry.managedAmount, + entry.startTime, + entry.endTime, + entry.periods, + entry.releaseStartTime, + entry.vestingCliffTime, + entry.revocable, + ) + const receipt = await waitTransaction(tx) + const event: Event = receipt.events[0] + const contractAddress = event.args['proxy'] + logger.success(`Deployed: ${contractAddress} (${entry.salt})`) + + // Save result + const deployResult = { ...entry, salt: entry.salt, txHash: tx.hash, contractAddress } + saveDeployResult(taskArgs.resultFile, deployResult) + } catch (err) { + logger.error(err) + } + }) + } + await queue.onIdle() + } else { + // Output tx builder json + logger.info(`Creating transaction builder JSON file...`) + const chainId = (await hre.ethers.provider.getNetwork()).chainId.toString() + const txBuilder = new TxBuilder(chainId, taskArgs.txBuilderTemplate) + + // Send funds to the manager + const grt = await hre.ethers.getContractAt('ERC20', tokenAddress) + const totalAmount = getTotalAmount(entries) + const currentBalance = await grt.balanceOf(manager.address) + if (currentBalance.lt(totalAmount)) { + logger.log('Building manager funding transactions...') + const remainingBalance = totalAmount.sub(currentBalance) + // Use GRT.approve + the manager deposit function instead of GRT.transfer to be super safe + const approveTx = await grt.populateTransaction.approve(manager.address, remainingBalance) + txBuilder.addTx({ + to: tokenAddress, + value: '0', + data: approveTx.data, + }) + const depositTx = await manager.populateTransaction.deposit(remainingBalance) + txBuilder.addTx({ + to: manager.address, + value: '0', + data: depositTx.data, + }) + } + + for (const entry of entries) { + logger.log('Building tx...') + logger.log(prettyConfigEntry(entry)) + const tx = await manager.populateTransaction.createTokenLockWallet( + entry.owner, + entry.beneficiary, + entry.managedAmount, + entry.startTime, + entry.endTime, + entry.periods, + entry.releaseStartTime, + entry.vestingCliffTime, + entry.revocable, + ) + txBuilder.addTx({ + to: manager.address, + value: '0', + data: tx.data, + }) + } + + // Save result into json file + const outputFile = txBuilder.saveToFile() + logger.success(`Transaction batch saved to ${outputFile}`) + } + }) + +task('create-token-locks-simple', 'Create token lock contracts from file') + .addParam('deployFile', 'File from where to read the deploy config') + .addParam('resultFile', 'File where to save results') + .addParam('tokenAddress', 'Token address to use in the contracts') + .addParam('ownerAddress', 'Owner address of token lock contracts') + .addOptionalParam('dryRun', 'Get the deterministic contract addresses but do not deploy', false, boolean) + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Prepare + logger.log(await prettyEnv(hre)) + + // Validations + const tokenAddress = taskArgs.tokenAddress + const ownerAddress = taskArgs.ownerAddress + isValidAddressOrFail(tokenAddress) + isValidAddressOrFail(ownerAddress) + + logger.info('Deploying token lock simple contracts...') + logger.log(`> GraphToken: ${tokenAddress}`) + + // Load config entries + logger.log('') + logger.info('Verifying deployment data...') + const entries = loadDeployData(taskArgs.deployFile) + if (!checkAddresses(entries)) { + process.exit(1) + } + logger.success(`Total of ${entries.length} entries. All good!`) + + // Check if Manager is funded + logger.log('') + logger.info('Verifying balances...') + const totalAmount = getTotalAmount(entries) + logger.log(`> Amount to distribute: ${formatEther(totalAmount)} GRT`) + + // Summary + if (!(await askConfirm())) { + logger.log('Cancelled') + process.exit(1) + } + + // Get accounts + const accounts = await hre.ethers.getSigners() + const deployer = accounts[0] + + // Deploy contracts + for (const entry of entries) { + logger.log('') + logger.info(`Creating contract...`) + logger.log(prettyConfigEntry(entry)) + + try { + const tokenLockSimpleFactory = await getContractFactory(hre, 'GraphTokenLockSimple') + const tokenLockSimpleDeployment = await tokenLockSimpleFactory.connect(deployer).deploy() + const tokenLockSimple = await tokenLockSimpleDeployment.deployed() + logger.success(`Deployed: ${tokenLockSimple.address}`) + + logger.log('Setting up...') + const tx = await tokenLockSimple.initialize( + ownerAddress, + entry.beneficiary, + tokenAddress, + entry.managedAmount, + entry.startTime, + entry.endTime, + entry.periods, + entry.releaseStartTime, + entry.vestingCliffTime, + entry.revocable, + ) + await waitTransaction(tx) + + // Save result + const deployResult = { ...entry, txHash: tx.hash, salt: '', contractAddress: tokenLockSimple.address } + saveDeployResult(taskArgs.resultFile, deployResult) + } catch (err) { + logger.log(err) + } + } + }) + +task('scan-token-locks-balances', 'Check current balances of deployed contracts') + .addParam('resultFile', 'File where to load deployed contracts') + .addParam('managerName', 'Name of the token lock manager deployment', 'GraphTokenLockManager') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Get contracts + const manager = await getTokenLockManagerOrFail(hre, taskArgs.managerName) + + // Prepare + logger.log(await prettyEnv(hre)) + + const tokenAddress = await manager.token() + + logger.info('Using:') + logger.log(`> GraphToken: ${tokenAddress}`) + logger.log(`> GraphTokenLockMasterCopy: ${await manager.masterCopy()}`) + logger.log(`> GraphTokenLockManager: ${manager.address}`) + + const grt = await hre.ethers.getContractAt('ERC20', tokenAddress) + const balance = await grt.balanceOf(manager.address) + logger.log('Current Manager balance is ', formatEther(balance)) + + // Load deployed entries + const deployedEntries = loadResultData('/' + taskArgs.resultFile) + + let balances = BigNumber.from(0) + for (const entry of deployedEntries) { + balances = balances.add(await grt.balanceOf(entry.contractAddress)) + } + logger.log(deployedEntries.length) + logger.log(formatEther(balances)) + }) diff --git a/packages/token-distribution/ops/delete.ts b/packages/token-distribution/ops/delete.ts new file mode 100644 index 000000000..1cb84c755 --- /dev/null +++ b/packages/token-distribution/ops/delete.ts @@ -0,0 +1,88 @@ +import { task } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { askConfirm, prettyEnv, waitTransaction } from './create' +import consola from 'consola' +import { TxBuilder } from './tx-builder' + +const logger = consola.create({}) + +const getTokenLockWalletOrFail = async (hre: HardhatRuntimeEnvironment, address: string) => { + const wallet = await hre.ethers.getContractAt('GraphTokenLockWallet', address) + try { + await wallet.deployed() + } catch (err) { + logger.error('GraphTokenLockWallet not deployed at', wallet.address) + process.exit(1) + } + + return wallet +} + +task('cancel-token-lock', 'Cancel token lock contract') + .addParam('contract', 'Address of the vesting contract to be cancelled') + .addFlag('dryRun', 'Get the deterministic contract addresses but do not deploy') + .addFlag( + 'txBuilder', + 'Output transaction batch in JSON format, compatible with Gnosis Safe transaction builder. Does not deploy contracts', + ) + .addOptionalParam('txBuilderTemplate', 'File to use as a template for the transaction builder') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Get contracts + const lockWallet = await getTokenLockWalletOrFail(hre, taskArgs.contract) + + // Prepare + logger.log(await prettyEnv(hre)) + + logger.info('Cancelling token lock contract...') + logger.log(`> GraphTokenLockWallet: ${lockWallet.address}`) + + // Check lock status + logger.log('Veryfing lock status...') + const lockAccepted = await lockWallet.isAccepted() + if (lockAccepted) { + logger.error('Lock was already accepted, use revoke() to revoke the vesting schedule') + process.exit(1) + } else { + logger.success(`Lock not accepted yet, preparing to cancel!`) + } + + // Nothing else to do, exit if dry run + if (taskArgs.dryRun) { + logger.info('Running in dry run mode!') + process.exit(0) + } + + if (!(await askConfirm())) { + logger.log('Cancelled') + process.exit(1) + } + + if (!taskArgs.txBuilder) { + const { deployer } = await hre.getNamedAccounts() + const lockOwner = await lockWallet.owner() + if (lockOwner !== deployer) { + logger.error('Only the owner can cancell the token lock') + process.exit(1) + } + + logger.info(`Cancelling contract...`) + const tx = await lockWallet.cancelLock() + await waitTransaction(tx) + logger.success(`Token lock at ${lockWallet.address} was cancelled`) + } else { + logger.info(`Creating transaction builder JSON file...`) + const chainId = (await hre.ethers.provider.getNetwork()).chainId.toString() + const txBuilder = new TxBuilder(chainId, taskArgs.txBuilderTemplate) + + const tx = await lockWallet.populateTransaction.cancelLock() + txBuilder.addTx({ + to: lockWallet.address, + data: tx.data, + value: 0, + }) + + // Save result into json file + const outputFile = txBuilder.saveToFile() + logger.success(`Transaction saved to ${outputFile}`) + } + }) diff --git a/packages/token-distribution/ops/deploy-data.csv b/packages/token-distribution/ops/deploy-data.csv new file mode 100644 index 000000000..3c56d705b --- /dev/null +++ b/packages/token-distribution/ops/deploy-data.csv @@ -0,0 +1,5 @@ +beneficiary,managedAmount,startTime,endTime,periods,revocable,releaseStartTime,vestingCliffTime +0xCF143e9dd5D64dE5ef096b291BAc195968A06D0d,250000.00,1627776000,1754006400,48,1,1659312000,0 +0x525ee071454cf9b6d750720bce8d8697ef82f02f,125000.00,1682899200,1777593600,36,1,1714435200,0 +0xBe243A5907071185d1bAeBa85C9E426DA797e4dD,909090.91,1696809600,1823040000,48,1,0,0 +0xD8068FEc14b3dd0223E21acfe978906556dAba99,500000.00,1697414400,1823644800,48,1,1728950400,0 \ No newline at end of file diff --git a/packages/token-distribution/ops/info.ts b/packages/token-distribution/ops/info.ts new file mode 100644 index 000000000..4906293df --- /dev/null +++ b/packages/token-distribution/ops/info.ts @@ -0,0 +1,758 @@ +import PQueue from 'p-queue' +import { task } from 'hardhat/config' +import '@nomiclabs/hardhat-ethers' +import { BigNumber, Contract, utils } from 'ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import CoinGecko from 'coingecko-api' +import { Block } from '@ethersproject/abstract-provider' +import * as GraphClient from '../.graphclient' +import { + CuratorWalletsDocument, + CuratorWalletsQuery, + execute, + GraphAccountDocument, + GraphAccountQuery, + GraphNetworkDocument, + GraphNetworkQuery, + TokenLockWalletsDocument, + TokenLockWalletsQuery, +} from '../.graphclient' +import { ExecutionResult } from 'graphql' + +const CoinGeckoClient = new CoinGecko() +const RPC_CONCURRENCY = 10 +const BLOCK_DRIFT = 10 + +// Types + +interface ContractTokenData { + address: string + tokenAmount: BigNumber +} + +type TokenLockWallet = Pick< + GraphClient.TokenLockWallet, + | 'id' + | 'beneficiary' + | 'managedAmount' + | 'periods' + | 'startTime' + | 'endTime' + | 'revocable' + | 'releaseStartTime' + | 'vestingCliffTime' + | 'initHash' + | 'txHash' + | 'manager' + | 'tokensReleased' + | 'tokensWithdrawn' + | 'tokensRevoked' + | 'blockNumberCreated' +> & { tokensUsed?: BigNumber } +type GraphNetwork = Pick +type GraphAccount = Pick & { + indexer?: Pick + curator?: Pick + delegator?: Pick +} + +// Helpers + +const toInt = s => parseInt(s) / 1e18 +const toBN = (s: string): BigNumber => BigNumber.from(s) +const formatGRT = (n: BigNumber): string => utils.formatEther(n) +const formatRoundGRT = (n: BigNumber): string => formatGRT(n).split('.')[0] +const parseGRT = (n: string): BigNumber => utils.parseEther(n) +const toWei = (n: string): string => parseGRT(n).toString() +const prettyDate = (date: string) => { + const n = parseInt(date) + if (n === 0) return '0' + const d = new Date(n * 1000) + return d.toISOString().replace(/T/, ' ').replace(/\..+/, '') +} +const now = () => +new Date() / 1000 + +// Fixed data + +const vestingListExchanges: TokenLockWallet[] = [ + { + beneficiary: '0x0000000000000000000000000000000000000000', + managedAmount: toWei('50000000'), + periods: 48, + startTime: '1522602000', + endTime: '1648832400', + revocable: 'Enabled', + releaseStartTime: '1627146000', + vestingCliffTime: '0', + id: '0x0000000000000000000000000000000000000000', + initHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + txHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + manager: '0x0000000000000000000000000000000000000000', + tokensReleased: '0', + tokensWithdrawn: '0', + tokensRevoked: '0', + blockNumberCreated: '0', + }, + { + beneficiary: '0x0000000000000000000000000000000000000000', + managedAmount: toWei('8000000'), + periods: 1, + startTime: '1608224400', + endTime: '1627146000', + revocable: 'Disabled', + releaseStartTime: '0', + vestingCliffTime: '0', + id: '0x0000000000000000000000000000000000000000', + initHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + txHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + manager: '0x0000000000000000000000000000000000000000', + tokensReleased: '0', + tokensWithdrawn: '0', + tokensRevoked: '0', + blockNumberCreated: '0', + }, + { + beneficiary: '0x0000000000000000000000000000000000000000', + managedAmount: toWei('59000000'), + periods: 48, + startTime: '1543683600', + endTime: '1669914000', + revocable: 'Enabled', + releaseStartTime: '1627146000', + vestingCliffTime: '0', + id: '0x0000000000000000000000000000000000000000', + initHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + txHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + manager: '0x0000000000000000000000000000000000000000', + tokensReleased: '0', + tokensWithdrawn: '0', + tokensRevoked: '0', + blockNumberCreated: '0', + }, + { + beneficiary: '0x0000000000000000000000000000000000000000', + managedAmount: toWei('4000000'), + periods: 1, + startTime: '1608224400', + endTime: '1627146000', + revocable: 'Disabled', + releaseStartTime: '0', + vestingCliffTime: '0', + id: '0x0000000000000000000000000000000000000000', + initHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + txHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + manager: '0x0000000000000000000000000000000000000000', + tokensReleased: '0', + tokensWithdrawn: '0', + tokensRevoked: '0', + blockNumberCreated: '0', + }, + { + beneficiary: '0x0000000000000000000000000000000000000000', + managedAmount: toWei('50000000'), + periods: 48, + startTime: '1527872400', + endTime: '1654102800', + revocable: 'Enabled', + releaseStartTime: '1627146000', + vestingCliffTime: '0', + id: '0x0000000000000000000000000000000000000000', + initHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + txHash: '0x0000000000000000000000000000000000000000000000000000000000000000', + manager: '0x0000000000000000000000000000000000000000', + tokensReleased: '0', + tokensWithdrawn: '0', + tokensRevoked: '0', + blockNumberCreated: '0', + }, +] + +// Network + +async function getNetworkData(blockNumber: number): Promise { + const result: ExecutionResult = await execute(GraphNetworkDocument, { blockNumber }) + return result.data.graphNetwork +} + +async function getWallets(blockNumber: number): Promise { + const result: ExecutionResult = await execute(TokenLockWalletsDocument, { + blockNumber, + first: 3_000, + }) + return result.data ? result.data.tokenLockWallets : [] +} + +async function getCuratorWallets(blockNumber: number): Promise { + const result: ExecutionResult = await execute(CuratorWalletsDocument, { + blockNumber, + first: 3_000, + }) + return result.data ? result.data.tokenLockWallets : [] +} + +async function getGraphAccount(accountId: string, blockNumber: number): Promise { + const result: ExecutionResult = await execute(GraphAccountDocument, { accountId, blockNumber }) + return result.data.graphAccount +} + +// Calculations + +function getAvailableAmount(wallet: TokenLockWallet, blockTimestamp: number): BigNumber { + const current = blockTimestamp + const startTime = parseInt(wallet.startTime) + const endTime = parseInt(wallet.endTime) + const managedAmount = toBN(wallet.managedAmount) + + if (current < startTime) { + return toBN('0') + } + if (current > parseInt(wallet.endTime)) { + return managedAmount + } + + const sinceStartTime = current > startTime ? current - startTime : 0 + const periodDuration = (endTime - startTime) / wallet.periods + const currentPeriod = Math.floor(sinceStartTime / periodDuration + 1) + const passedPeriods = currentPeriod - 1 + const amountPerPeriod = managedAmount.div(wallet.periods) + + return amountPerPeriod.mul(passedPeriods) +} + +// Returns the amount of tokens that are free to be withdrawn +// Note that this is different than availableAmount() and releasableAmount() +function getFreeAmount(wallet: TokenLockWallet, blockTimestamp: number): BigNumber { + const current = blockTimestamp + const releaseStartTime = parseInt(wallet.releaseStartTime) + const vestingCliffTime = parseInt(wallet.vestingCliffTime) + + if (releaseStartTime > 0 && releaseStartTime > current) { + return toBN('0') + } + + if (wallet.revocable === 'Enabled' && vestingCliffTime > 0 && vestingCliffTime > current) { + return toBN('0') + } + + return getAvailableAmount(wallet, blockTimestamp) +} + +type WalletInfo = { + tokensUsed: BigNumber + tokensBalance: BigNumber + graphAccount: GraphAccount + owner: string +} + +async function getExtendedWalletInfo( + contracts: Contract[], + blockNumber: number, +): Promise<{ [key: string]: WalletInfo }> { + const walletInfoEntries: { [key: string]: WalletInfo } = {} + const queue = new PQueue({ concurrency: RPC_CONCURRENCY }) + + void contracts.map(async (contract) => { + await queue.add(async () => { + // Get subgraph data + const graphAccount = await getGraphAccount(contract.address, blockNumber) + + // Get on-chain data + const tokensUsed = await contract.usedAmount({ blockTag: blockNumber }) + const tokensBalance = await contract.currentBalance({ blockTag: blockNumber }) + const owner = await contract.owner({ blockTag: blockNumber }) + + // Populate extra data + walletInfoEntries[contract.address] = { + tokensUsed, + tokensBalance, + graphAccount, + owner, + } + }) + }) + await queue.onIdle() + + return walletInfoEntries +} + +// Summaries + +class TokenSummary { + totalManaged: BigNumber + totalReleased: BigNumber + totalAvailable: BigNumber + totalFree: BigNumber + totalUsed: BigNumber + totalCount: number + contractsReleased: ContractTokenData[] + contractsInProtocol: ContractTokenData[] + block: Block + + constructor(block: Block) { + this.totalManaged = BigNumber.from(0) + this.totalReleased = BigNumber.from(0) + this.totalAvailable = BigNumber.from(0) + this.totalFree = BigNumber.from(0) + this.totalUsed = BigNumber.from(0) + this.totalCount = 0 + this.contractsReleased = [] + this.contractsInProtocol = [] + this.block = block + } + + public async addWallet(wallet: TokenLockWallet, contract?: Contract) { + const availableAmount = getAvailableAmount(wallet, this.block.timestamp) + const freeAmount = getFreeAmount(wallet, this.block.timestamp) + const tokensReleased = toBN(wallet.tokensReleased) + + this.totalManaged = this.totalManaged.add(toBN(wallet.managedAmount)) + this.totalAvailable = this.totalAvailable.add(availableAmount) + this.totalFree = this.totalFree.add(freeAmount) + this.totalReleased = this.totalReleased.add(tokensReleased) + this.totalCount++ + + if (tokensReleased.gt(0)) { + this.contractsReleased.push({ address: wallet.id, tokenAmount: tokensReleased }) + } + + if (contract) { + const [usedAmount] = await Promise.all([contract.usedAmount({ blockTag: this.block.number })]) + if (usedAmount.gt(0)) { + this.totalUsed = this.totalUsed.add(usedAmount) + this.contractsInProtocol.push({ address: contract.address, tokenAmount: usedAmount }) + } + } + } + + private showContracts(contracts: ContractTokenData[]) { + for (const contractTokenData of contracts) { + console.log(` ${contractTokenData.address}: ${formatRoundGRT(contractTokenData.tokenAmount)}`) + } + } + + public show(detail = false) { + console.log(`= Managed: ${formatRoundGRT(this.totalManaged)} [n:${this.totalCount}]`) + console.log( + `- Available (${this.totalAvailable.mul(100).div(this.totalManaged).toString()}%):`, + formatRoundGRT(this.totalAvailable), + ) + console.log(`- Free (${this.totalFree.mul(100).div(this.totalManaged).toString()}%):`, formatRoundGRT(this.totalFree)) + console.log( + `-- Released (${this.totalFree.gt(0) ? this.totalReleased.mul(100).div(this.totalFree).toString() : 0}%): ${formatRoundGRT( + this.totalReleased, + )} [n:${this.contractsReleased.length}]`, + ) + if (detail) { + this.showContracts(this.contractsReleased) + } + if (this.totalUsed.gt(0)) { + console.log(`- Used ${formatRoundGRT(this.totalUsed)} [n:${this.contractsInProtocol.length}]`) + if (detail) { + this.showContracts(this.contractsInProtocol) + } + } + } +} + +// -- Tasks -- + +task('contracts:list', 'List all token lock contracts') + .addOptionalParam('blocknumber', 'Block number to list contracts on') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // fetch block + const targetBlockNumber = taskArgs.blocknumber ? parseInt(taskArgs.blocknumber) : 'latest' + const block = await hre.ethers.provider.getBlock(targetBlockNumber) + const blockNumber = block.number - BLOCK_DRIFT + console.log('Block:', block.number, '/', new Date(block.timestamp * 1000).toDateString(), '\n') + + // fetch wallets + console.log('Fetching wallets...') + const allWallets = await getWallets(blockNumber) + console.log(`${allWallets.length} wallets found`) + + // populate token amounts used in the protocol + console.log('Populating used amounts...') + const extendedWalletInfo = await getExtendedWalletInfo( + await Promise.all( + allWallets.map(async (wallet) => { + return hre.ethers.getContractAt('GraphTokenLockWallet', wallet.id) + }), + ), + blockNumber, + ) + + const headers = [ + 'beneficiary', + 'managedAmount', + 'startTime', + 'endTime', + 'periods', + 'revocable', + 'releaseStartTime', + 'vestingCliffTime', + 'contractAddress', + 'initHash', + 'txHash', + 'manager', + 'owner', + 'tokensReleased', + 'tokensWithdrawn', + 'tokensAvailable', + 'tokensRevoked', + 'tokensUsed', + 'tokensBalance', + 'blockNumberCreated', + 'tokensUsedStaked', + 'tokensUsedDelegated', + ].join(',') + console.log(headers) + + for (const wallet of allWallets) { + // get used tokens in the protocol + const extendedWallet = extendedWalletInfo[wallet.id] + const { graphAccount, tokensUsed, tokensBalance, owner } = extendedWallet + const tokensUsedStaked = BigNumber.from(graphAccount.indexer?.stakedTokens || 0) + const tokensUsedDelegated = graphAccount.delegator + ? BigNumber.from(graphAccount.delegator.totalStakedTokens).sub( + BigNumber.from(graphAccount.delegator.totalUnstakedTokens), + ) + : BigNumber.from(0) + + // print wallet entries + const csv = [ + wallet.beneficiary, + toInt(wallet.managedAmount), + wallet.startTime, + wallet.endTime, + wallet.periods, + wallet.revocable, + wallet.releaseStartTime, + wallet.vestingCliffTime, + wallet.id, + wallet.initHash, + wallet.txHash, + wallet.manager, + owner, + toInt(wallet.tokensReleased), + toInt(wallet.tokensWithdrawn), + formatGRT(getAvailableAmount(wallet, block.timestamp)), + toInt(wallet.tokensRevoked), + formatGRT(tokensUsed), + formatGRT(tokensBalance), + wallet.blockNumberCreated, + formatGRT(tokensUsedStaked), + formatGRT(tokensUsedDelegated), + ].join(',') + console.log(csv) + } + }) + +task('contracts:curators', 'Show overview of curator vesting contracts') + .addOptionalParam('blocknumber', 'Block number to list contracts on') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + const blockNumber = taskArgs.blocknumber ? parseInt(taskArgs.blocknumber) : 'latest' + const block = await hre.ethers.provider.getBlock(blockNumber) + console.log('Block:', block.number, '/', new Date(block.timestamp * 1000).toDateString(), '\n') + + const allWallets = await getCuratorWallets(block.number) + const managedAmount = allWallets.reduce((acc, wallet) => acc.add(toBN(wallet.managedAmount)), BigNumber.from(0)) + + console.log(`Found ${allWallets.length} curator wallets.`) + console.log(`Total managed amount: ${formatRoundGRT(managedAmount)}`) + console.log(`First curator contract deployed at block ${allWallets[0].blockNumberCreated}`) + console.log(`Last curator contract deployed at block ${allWallets[allWallets.length - 1].blockNumberCreated}`) + }) + +task('contracts:summary', 'Show summary of balances') + .addOptionalParam('blocknumber', 'Block number to calculate balances on') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Fetch contracts + const blockNumber = taskArgs.blocknumber ? parseInt(taskArgs.blocknumber) : 'latest' + const block = await hre.ethers.provider.getBlock(blockNumber) + console.log('Block:', block.number, '/', new Date(block.timestamp * 1000).toDateString(), '\n') + const allWallets = await getWallets(block.number) + const revocableWallets = allWallets.filter(wallet => wallet.revocable === 'Enabled') + + // Calculate summaries (for all vestings) + const summary: TokenSummary = new TokenSummary(block) + for (const wallet of allWallets) { + await summary.addWallet(wallet) + } + + // Calculate summaries (for revocable vestings) + const queue = new PQueue({ concurrency: RPC_CONCURRENCY }) + const revocableSummary: TokenSummary = new TokenSummary(block) + void revocableWallets.map(async (wallet) => { + await queue.add(async () => { + const contract = await hre.ethers.getContractAt('GraphTokenLockWallet', wallet.id) + await revocableSummary.addWallet(wallet, contract) + }) + }) + await queue.onIdle() + + // Network data + const graphNetwork = await getNetworkData(block.number) + + // Foundation and Edge & Node contracts + const vestingEAN = await hre.ethers.getContractAt( + 'GraphTokenLockSimple', + '0x5785176048BEB00DcB6eC84A604d76E30E0666db', + ) + const vestingGRT = await hre.ethers.getContractAt( + 'GraphTokenLockSimple', + '0x32Ec7A59549b9F114c9D7d8b21891d91Ae7F2ca1', + ) + + // EAN and GRT vesting contracts have releaseStartTime = 0 and vestingCliffTime = 0 + // so we can consider that availableAmount == freeAmount + const [managedAmountEAN, managedAmountGRT, availableAmountEAN, availableAmountGRT] = await Promise.all([ + await vestingEAN.managedAmount({ blockTag: block.number }), + await vestingGRT.managedAmount({ blockTag: block.number }), + await vestingEAN.availableAmount({ blockTag: block.number }), + await vestingGRT.availableAmount({ blockTag: block.number }), + ]) + + // Exchange locked + let managedAmountExchanges = vestingListExchanges + .map(vesting => toBN(vesting.managedAmount)) + .reduce((a, b) => a.add(b), toBN('0')) + let freeAmountExchanges = vestingListExchanges + .map(vesting => getFreeAmount(vesting, block.timestamp)) + .reduce((a, b) => a.add(b), toBN('0')) + managedAmountExchanges = managedAmountExchanges.add(toWei('283333334')) + freeAmountExchanges = freeAmountExchanges.add(toWei('150000000')) + + // General summary + const totalSupply = toBN(graphNetwork.totalSupply) + const totalLockedAll = summary.totalManaged.sub(summary.totalFree) + const totalLockedEAN = managedAmountEAN.sub(availableAmountEAN) + const totalLockedGRT = managedAmountGRT.sub(availableAmountGRT) + const totalLockedExchanges = managedAmountExchanges.sub(freeAmountExchanges) + const totalLocked = totalLockedAll.add(totalLockedEAN).add(totalLockedGRT).add(totalLockedExchanges) + + console.log('General Summary') + console.log('---------------') + console.log('= Total Supply:\t', formatRoundGRT(totalSupply)) + console.log('- Total Locked:\t', formatRoundGRT(totalLocked)) + console.log('-- General:\t', formatRoundGRT(totalLockedAll), '/', formatRoundGRT(summary.totalManaged)) + console.log('-- Edge & Node:\t', formatRoundGRT(totalLockedEAN), '/', formatRoundGRT(managedAmountEAN)) + console.log('-- Foundation:\t', formatRoundGRT(totalLockedGRT), '/', formatRoundGRT(managedAmountGRT)) + console.log('-- Exchanges:\t', formatRoundGRT(totalLockedExchanges), '/', formatRoundGRT(managedAmountExchanges)) + console.log('- Total Free:\t', formatRoundGRT(totalSupply.sub(totalLocked))) + console.log('') + summary.show() + + // Summary of revocable contracts + console.log('\nRevocable Summary') + console.log('-----------------') + revocableSummary.show(false) + }) + +task('contracts:show', 'Show info about an specific contract') + .addPositionalParam('address', 'Contract address to show') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + const contractAddress = taskArgs.address + const contract = await hre.ethers.getContractAt('GraphTokenLockWallet', contractAddress) + + const [ + managedAmount, + availableAmount, + releasableAmount, + releasedAmount, + usedAmount, + currentBalance, + amountPerPeriod, + surplusAmount, + vestedAmount, + ] = await Promise.all([ + await contract.managedAmount(), + await contract.availableAmount(), + await contract.releasableAmount(), + await contract.releasedAmount(), + await contract.usedAmount(), + await contract.currentBalance(), + await contract.amountPerPeriod(), + await contract.surplusAmount(), + await contract.vestedAmount(), + ]).then(results => results.map(e => formatRoundGRT(e))) + + const [startTime, endTime, periods, currentPeriod, periodDuration, revocable, owner, manager] = await Promise.all([ + contract.startTime(), + contract.endTime(), + contract.periods(), + contract.currentPeriod(), + contract.periodDuration(), + contract.revocable(), + contract.owner(), + contract.manager(), + ]) + const nextTime = startTime.add(currentPeriod.mul(periodDuration)) + + console.log(`# Contract at ${contractAddress}`) + console.log('\n## Control') + console.log(` Owner: ${owner}`) + console.log(` Manager: ${manager}`) + console.log('\n## Schedule') + console.log(` ${prettyDate(startTime)} -> ${prettyDate(endTime)} <@${periods} periods>`) + console.log(` Next: ${prettyDate(nextTime)} >> ${amountPerPeriod}`) + console.log(` Revocable: ${revocable}`) + console.log(' (=) Managed:', managedAmount) + console.log(' - Available: ', availableAmount) + console.log(' - Unvested: ', formatRoundGRT(parseGRT(managedAmount).sub(parseGRT(vestedAmount)))) + console.log(' - Releaseable: ', releasableAmount) + console.log('\n## Position') + console.log(' (*) Managed:', managedAmount) + console.log(' (=) Balance:', currentBalance) + console.log(' (<) Released: ', releasedAmount) + console.log(' (>) Used: ', usedAmount) + console.log(' (+) Surplus: ', surplusAmount) + }) + +interface CoinPrice { + date: number + price: number +} + +async function getCoinPrice(timeIndex: number): Promise { + // Scan for a price close to the desired datetime + const buffer = 1800 + const params = { + from: timeIndex - buffer, + to: timeIndex + buffer, + } + const coin = await CoinGeckoClient.coins.fetchMarketChartRange('the-graph', params) + const priceInstance = coin.data.prices[0] + return { + date: priceInstance[0] / 1000, + price: priceInstance[1], + } +} + +task('contracts:schedule', 'Show schedule of a set of contracts').setAction( + async (_, hre: HardhatRuntimeEnvironment) => { + const contractAddresses = [ + '0xc2525d1326c0d38c9fae42a663b9ec32a6338948', + '0xc4307eb08c3fd10c1f7de94e6db34371df18f06f', + '0x4c57e626f38a95220eefa8fc2f44ef5e4bbc7b9e', + '0x56f256fdd8899fd3f08b731431c61e2df8f99625', + '0x60abb93f12ebbbfd84c8cb52df8c7b3c26aea170', + '0x1d535b18ee9b8453cfef723ecd96720c3322de8c', + '0x27c26eed0a9e09d9662eb154f52b55153d2ed705', + ] + + // Print release schedule for every contract + for (const contractAddress of contractAddresses) { + // Read contract data + const contract = await hre.ethers.getContractAt('GraphTokenLockWallet', contractAddress) + const [startTime, endTime, periods, amountPerPeriod] = await Promise.all([ + contract.startTime(), + contract.endTime(), + contract.periods(), + contract.amountPerPeriod(), + ]) + + // Scan every period + const duration = endTime.sub(startTime) + const durationPerPeriod = duration.div(periods) + for (let i = 1; i <= periods; i++) { + const timeIndex = startTime.add(durationPerPeriod.mul(i)) + const output = [contractAddress, i, prettyDate(timeIndex.toString()), formatGRT(amountPerPeriod)] + if (timeIndex < now()) { + try { + const coinPrice = await getCoinPrice(timeIndex.toNumber()) + output.push(coinPrice.price) + output.push(prettyDate(coinPrice.date.toString())) + console.log(output.join(',')) + } catch (e) { + console.log(e) + console.log('Error while fetching coin price') + console.log(output) + break + } + } else { + output.push('') + output.push('') + } + } + } + }, +) + +task('contracts:list-pending-lock', 'List all token lock contracts that have not accepted the lock') + .addOptionalParam('blocknumber', 'Block number to list contracts on') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + const blockNumber = taskArgs.blocknumber ? parseInt(taskArgs.blocknumber) : 'latest' + const block = await hre.ethers.provider.getBlock(blockNumber) + console.log('Block:', block.number, '/', new Date(block.timestamp * 1000).toDateString(), '\n') + + // Get all wallets + const allWallets = await getWallets(block.number) + console.log(`Found ${allWallets.length} wallets total`) + + // get isAccepted from chain, not part of the subgraph + console.log(`Checking lock status...`) + const queue = new PQueue({ concurrency: RPC_CONCURRENCY }) + const pendingLocks: TokenLockWallet[] = [] + void allWallets.map(async (wallet) => { + await queue.add(async () => { + // Original contract didn't support accepting/cancelling lock, we can safely ignore those + // so we wrap isAccepted() call in try/catch and keep going if it fails + try { + const contract = await hre.ethers.getContractAt('GraphTokenLockWallet', wallet.id) + const isAccepted = await contract.isAccepted() + if (!isAccepted) { + pendingLocks.push(wallet) + } + } catch (error) { + console.log(`Could not call isAccepted() on ${wallet.id}.`) + } + }) + }) + await queue.onIdle() + + console.log(`Found ${pendingLocks.length} wallets pending lock acceptance!`) + + const headers = [ + 'beneficiary', + 'managedAmount', + 'startTime', + 'endTime', + 'periods', + 'revocable', + 'releaseStartTime', + 'vestingCliffTime', + 'contractAddress', + 'initHash', + 'txHash', + 'manager', + 'tokensReleased', + 'tokensWithdrawn', + 'tokensAvailable', + 'tokensRevoked', + 'blockNumberCreated', + ].join(',') + console.log(headers) + + for (const wallet of pendingLocks) { + const csv = [ + wallet.beneficiary, + toInt(wallet.managedAmount), + wallet.startTime, + wallet.endTime, + wallet.periods, + wallet.revocable, + wallet.releaseStartTime, + wallet.vestingCliffTime, + wallet.id, + wallet.initHash, + wallet.txHash, + wallet.manager, + toInt(wallet.tokensReleased), + toInt(wallet.tokensWithdrawn), + formatRoundGRT(getAvailableAmount(wallet, block.timestamp)), + toInt(wallet.tokensRevoked), + wallet.blockNumberCreated, + ].join(',') + console.log(csv) + } + }) diff --git a/packages/token-distribution/ops/manager.ts b/packages/token-distribution/ops/manager.ts new file mode 100644 index 000000000..ea92bc615 --- /dev/null +++ b/packages/token-distribution/ops/manager.ts @@ -0,0 +1,164 @@ +import { task } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { askConfirm, getTokenLockManagerOrFail, isValidAddressOrFail, prettyEnv, waitTransaction } from './create' +import consola from 'consola' +import { formatEther, parseEther } from 'ethers/lib/utils' + +const logger = consola.create({}) + +task('manager-setup-auth', 'Setup default authorized functions in the manager') + .addParam('targetAddress', 'Target address for function calls') + .addParam('managerName', 'Name of the token lock manager deployment', 'GraphTokenLockManager') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Get contracts + const manager = await getTokenLockManagerOrFail(hre, taskArgs.managerName) + + logger.info('Setting up authorized functions...') + logger.log(`> GraphTokenLockManager: ${manager.address}`) + logger.log(`> Staking: ${taskArgs.targetAddress}`) + + // Prepare + logger.log(await prettyEnv(hre)) + + // Validations + isValidAddressOrFail(taskArgs.targetAddress) + + // Setup authorized functions + const signatures = [ + 'stake(uint256)', + 'unstake(uint256)', + 'withdraw()', + 'delegate(address,uint256)', + 'undelegate(address,uint256)', + 'withdrawDelegated(address,address)', + 'setDelegationParameters(uint32,uint32,uint32)', + 'setOperator(address,bool)', + ] + + logger.info('The following signatures will be authorized:') + logger.info(signatures) + + if (await askConfirm()) { + // Setup authorized functions + logger.info('Setup authorized functions...') + const targets = Array(signatures.length).fill(taskArgs.targetAddress) + const tx1 = await manager.setAuthFunctionCallMany(signatures, targets) + await waitTransaction(tx1) + logger.success('Done!\n') + + // Setup authorized token destinations + logger.info('Setup authorized destinations...') + const tx2 = await manager.addTokenDestination(taskArgs.targetAddress) + await waitTransaction(tx2) + } + }) + +task('manager-deposit', 'Deposit fund into the manager') + .addParam('amount', 'Amount to deposit in GRT') + .addParam('managerName', 'Name of the token lock manager deployment', 'GraphTokenLockManager') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Get contracts + const manager = await getTokenLockManagerOrFail(hre, taskArgs.managerName) + + // Prepare + logger.log(await prettyEnv(hre)) + + const tokenAddress = await manager.token() + + logger.info('Using:') + logger.log(`> GraphToken: ${tokenAddress}`) + logger.log(`> GraphTokenLockMasterCopy: ${await manager.masterCopy()}`) + logger.log(`> GraphTokenLockManager: ${manager.address}`) + + // Deposit funds + logger.log(`You are depositing ${taskArgs.amount} into ${manager.address}...`) + if (await askConfirm()) { + const weiAmount = parseEther(taskArgs.amount) + + logger.log('Approve...') + const grt = await hre.ethers.getContractAt('ERC20', tokenAddress) + const tx1 = await grt.approve(manager.address, weiAmount) + await waitTransaction(tx1) + + logger.log('Deposit...') + const tx2 = await manager.deposit(weiAmount) + await waitTransaction(tx2) + } + }) + +task('manager-withdraw', 'Withdraw fund from the manager') + .addParam('amount', 'Amount to deposit in GRT') + .addParam('managerName', 'Name of the token lock manager deployment', 'GraphTokenLockManager') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Get contracts + const manager = await getTokenLockManagerOrFail(hre, taskArgs.managerName) + + // Prepare + logger.log(await prettyEnv(hre)) + + const tokenAddress = await manager.token() + + logger.info('Using:') + logger.log(`> GraphToken: ${tokenAddress}`) + logger.log(`> GraphTokenLockMasterCopy: ${await manager.masterCopy()}`) + logger.log(`> GraphTokenLockManager: ${manager.address}`) + + // Withdraw funds + logger.log(`You are withdrawing ${taskArgs.amount} from ${manager.address}...`) + if (await askConfirm()) { + const weiAmount = parseEther(taskArgs.amount) + + logger.log('Deposit...') + const tx = await manager.withdraw(weiAmount) + await waitTransaction(tx) + } + }) + +task('manager-balance', 'Get current manager balance') + .addParam('managerName', 'Name of the token lock manager deployment', 'GraphTokenLockManager') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + // Get contracts + const manager = await getTokenLockManagerOrFail(hre, taskArgs.managerName) + + // Prepare + logger.log(await prettyEnv(hre)) + + const tokenAddress = await manager.token() + const managerOwnerAddress = await manager.owner() + + logger.info('Using:') + logger.log(`> GraphToken: ${tokenAddress}`) + logger.log(`> GraphTokenLockMasterCopy: ${await manager.masterCopy()}`) + logger.log(`> GraphTokenLockManager: ${manager.address} owner: ${managerOwnerAddress}`) + + const grt = await hre.ethers.getContractAt('ERC20', tokenAddress) + const balance = await grt.balanceOf(manager.address) + logger.log('Current Manager balance is ', formatEther(balance)) + }) + +task('manager-transfer-ownership', 'Transfer ownership of the manager') + .addParam('owner', 'Address of the new owner') + .addParam('managerName', 'Name of the token lock manager deployment', 'GraphTokenLockManager') + .setAction(async (taskArgs, hre: HardhatRuntimeEnvironment) => { + const manager = await getTokenLockManagerOrFail(hre, taskArgs.managerName) + + // Validate current owner + const tokenLockManagerOwner = await manager.owner() + const { deployer } = await hre.getNamedAccounts() + if (tokenLockManagerOwner !== deployer) { + logger.error('Only the owner can transfer ownership') + process.exit(1) + } + + logger.info(`Manager address: ${manager.address}}`) + logger.info(`Current owner: ${tokenLockManagerOwner}`) + logger.info(`New owner: ${taskArgs.owner}`) + + if (!(await askConfirm())) { + logger.log('Cancelled') + process.exit(1) + } + + // Transfer ownership + await manager.transferOwnership(taskArgs.owner) + }) diff --git a/packages/token-distribution/ops/queries/account.graphql b/packages/token-distribution/ops/queries/account.graphql new file mode 100644 index 000000000..d97f4b388 --- /dev/null +++ b/packages/token-distribution/ops/queries/account.graphql @@ -0,0 +1,17 @@ +query GraphAccount($accountId: ID!, $blockNumber: Int) { + graphAccount(id: $accountId, block: { number: $blockNumber }) { + id + indexer { + stakedTokens + } + curator { + totalSignalledTokens + totalUnsignalledTokens + } + delegator { + totalStakedTokens + totalUnstakedTokens + totalRealizedRewards + } + } +} diff --git a/packages/token-distribution/ops/queries/curators.graphql b/packages/token-distribution/ops/queries/curators.graphql new file mode 100644 index 000000000..586a00b2c --- /dev/null +++ b/packages/token-distribution/ops/queries/curators.graphql @@ -0,0 +1,25 @@ +query CuratorWallets($blockNumber: Int, $first: Int) { + tokenLockWallets( + block: { number: $blockNumber } + where: { periods: 16, startTime: 1608224400, endTime: 1734454800, revocable: Disabled } + first: $first + orderBy: blockNumberCreated + ) { + id + beneficiary + managedAmount + periods + startTime + endTime + revocable + releaseStartTime + vestingCliffTime + initHash + txHash + manager + tokensReleased + tokensWithdrawn + tokensRevoked + blockNumberCreated + } +} \ No newline at end of file diff --git a/packages/token-distribution/ops/queries/network.graphql b/packages/token-distribution/ops/queries/network.graphql new file mode 100644 index 000000000..f305a3278 --- /dev/null +++ b/packages/token-distribution/ops/queries/network.graphql @@ -0,0 +1,6 @@ +query GraphNetwork($blockNumber: Int) { + graphNetwork(id: 1, block: { number: $blockNumber }) { + id + totalSupply + } +} \ No newline at end of file diff --git a/packages/token-distribution/ops/queries/tokenLockWallets.graphql b/packages/token-distribution/ops/queries/tokenLockWallets.graphql new file mode 100644 index 000000000..4ab3d5ba7 --- /dev/null +++ b/packages/token-distribution/ops/queries/tokenLockWallets.graphql @@ -0,0 +1,20 @@ +query TokenLockWallets($blockNumber: Int, $first: Int) { + tokenLockWallets(block: { number: $blockNumber }, first: $first, orderBy: id) { + id + beneficiary + managedAmount + periods + startTime + endTime + revocable + releaseStartTime + vestingCliffTime + initHash + txHash + manager + tokensReleased + tokensWithdrawn + tokensRevoked + blockNumberCreated + } +} diff --git a/packages/token-distribution/ops/results.csv b/packages/token-distribution/ops/results.csv new file mode 100644 index 000000000..e69de29bb diff --git a/packages/token-distribution/ops/tx-builder-template.json b/packages/token-distribution/ops/tx-builder-template.json new file mode 100644 index 000000000..0dbac0044 --- /dev/null +++ b/packages/token-distribution/ops/tx-builder-template.json @@ -0,0 +1,15 @@ +{ + "version": "1.0", + "chainId": "5", + "createdAt": 1664999924896, + "meta": { + "name": "Vesting Contracts", + "description": "", + "txBuilderVersion": "1.11.1", + "createdFromSafeAddress": "", + "createdFromOwnerAddress": "", + "checksum": "0xaa4f6084a39579ddecb1224904d703183c5086d1e3d7e63ba94a8b6819dd2122" + }, + "transactions": [ + ] +} diff --git a/packages/token-distribution/ops/tx-builder.ts b/packages/token-distribution/ops/tx-builder.ts new file mode 100644 index 000000000..6a6f200d7 --- /dev/null +++ b/packages/token-distribution/ops/tx-builder.ts @@ -0,0 +1,45 @@ +import fs from 'fs' +import path from 'path' + +export interface BuilderTx { + to: string + data: string + value: number | string + contractMethod?: null + contractInputsValues?: null +} + +interface TxBuilderContents { + createdAt: number + chainId: string + transactions: BuilderTx[] +} + +export class TxBuilder { + contents: TxBuilderContents + outputFile: string + + constructor(chainId: string, _template?: string) { + // Template file + const template = _template ?? 'tx-builder-template.json' + const templateFilename = path.join(__dirname, template) + + // Output file + const dateTime = new Date().getTime() + this.outputFile = path.join(__dirname, `tx-builder-${dateTime}.json`) + + // Load template + this.contents = JSON.parse(fs.readFileSync(templateFilename, 'utf8')) + this.contents.createdAt = dateTime + this.contents.chainId = chainId + } + + addTx(tx: BuilderTx) { + this.contents.transactions.push({ ...tx, contractMethod: null, contractInputsValues: null }) + } + + saveToFile() { + fs.writeFileSync(this.outputFile, JSON.stringify(this.contents, null, 2)) + return this.outputFile + } +} diff --git a/packages/token-distribution/package.json b/packages/token-distribution/package.json new file mode 100644 index 000000000..37069fc41 --- /dev/null +++ b/packages/token-distribution/package.json @@ -0,0 +1,70 @@ +{ + "name": "@graphprotocol/token-distribution", + "version": "1.2.0", + "description": "Graph Token Distribution", + "main": "index.js", + "scripts": { + "prepublishOnly": "scripts/prepublish", + "build": "scripts/build", + "clean": "rm -rf build/ cache/ dist/ && hardhat clean", + "compile": "hardhat compile --show-stack-traces", + "deploy": "yarn run build && hardhat deploy", + "test": "scripts/test", + "test:gas": "RUN_EVM=true REPORT_GAS=true scripts/test", + "test:coverage": "scripts/coverage", + "lint": "yarn run lint:ts && yarn run lint:sol", + "lint:ts": "eslint '**/*.{js,ts}' --fix", + "lint:sol": "prettier --write contracts/**/*.sol && solhint --fix contracts/**/*.sol --config node_modules/solhint-graph-config/index.js", + "security": "scripts/security", + "flatten": "scripts/flatten", + "typechain": "hardhat typechain", + "verify": "hardhat verify", + "size": "hardhat size-contracts" + }, + "files": [ + "dist/**/*", + "README.md", + "LICENSE" + ], + "author": "The Graph Team", + "license": "MIT", + "devDependencies": { + "@ethersproject/experimental": "^5.0.7", + "@graphprotocol/client-cli": "^2.0.2", + "@graphprotocol/contracts": "^5.0.0", + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.1.7", + "@nomiclabs/hardhat-waffle": "^2.0.0", + "@openzeppelin/contracts": "^3.3.0-solc-0.7", + "@openzeppelin/contracts-upgradeable": "3.4.2", + "@openzeppelin/hardhat-upgrades": "^1.22.1", + "@typechain/ethers-v5": "^7.0.0", + "@typechain/hardhat": "^2.0.0", + "@types/mocha": "^9.1.0", + "@types/node": "^20.4.2", + "chai": "^4.2.0", + "coingecko-api": "^1.0.10", + "consola": "^2.15.0", + "dotenv": "^16.0.0", + "eslint": "^8.56.0", + "eslint-graph-config": "workspace:^", + "ethereum-waffle": "^3.1.1", + "ethers": "^5.0.18", + "graphql": "^16.5.0", + "hardhat": "^2.6.1", + "hardhat-abi-exporter": "^2.0.1", + "hardhat-contract-sizer": "^2.0.1", + "hardhat-deploy": "^0.7.0-beta.9", + "hardhat-gas-reporter": "^1.0.1", + "inquirer": "8.0.0", + "p-queue": "^6.6.2", + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1", + "solhint-community": "^3.7.0", + "solhint-graph-config": "workspace:^0.0.1", + "solhint-plugin-prettier": "^0.1.0", + "ts-node": "^10.9.1", + "typechain": "^5.0.0", + "typescript": "^4.0.2" + } +} diff --git a/packages/token-distribution/prettier.config.js b/packages/token-distribution/prettier.config.js new file mode 100644 index 000000000..5b8e866f2 --- /dev/null +++ b/packages/token-distribution/prettier.config.js @@ -0,0 +1,2 @@ +const prettierGraphConfig = require('solhint-graph-config/prettier') +module.exports = prettierGraphConfig diff --git a/packages/token-distribution/scripts/build b/packages/token-distribution/scripts/build new file mode 100755 index 000000000..7805eacb4 --- /dev/null +++ b/packages/token-distribution/scripts/build @@ -0,0 +1,6 @@ +#!/bin/bash + +set -eo pipefail + +yarn graphclient build +yarn run compile \ No newline at end of file diff --git a/packages/token-distribution/scripts/coverage b/packages/token-distribution/scripts/coverage new file mode 100755 index 000000000..9252ae7b6 --- /dev/null +++ b/packages/token-distribution/scripts/coverage @@ -0,0 +1,6 @@ +#!/bin/bash + +set -eo pipefail + +yarn run compile +npx hardhat coverage $@ diff --git a/packages/token-distribution/scripts/flatten b/packages/token-distribution/scripts/flatten new file mode 100755 index 000000000..763384ff3 --- /dev/null +++ b/packages/token-distribution/scripts/flatten @@ -0,0 +1,24 @@ +#!/bin/bash + +OUT_DIR="build/flatten" + +mkdir -p ${OUT_DIR} + +echo "Flattening contracts..." + +FILES=( + "contracts/GraphTokenDistributor.sol" + "contracts/GraphTokenLockSimple.sol" + "contracts/GraphTokenLockWallet.sol" + "contracts/GraphTokenLockManager.sol" +) + +for path in ${FILES[@]}; do + IFS='/' + parts=( $path ) + name=${parts[${#parts[@]}-1]} + echo "Flatten > ${name}" + hardhat flatten "${path}" > "${OUT_DIR}/${name}" +done + +echo "Done!" diff --git a/packages/token-distribution/scripts/prepublish b/packages/token-distribution/scripts/prepublish new file mode 100755 index 000000000..73c84821d --- /dev/null +++ b/packages/token-distribution/scripts/prepublish @@ -0,0 +1,26 @@ +#!/bin/bash + +TYPECHAIN_DIR=dist/types + +set -eo pipefail + +# Build contracts +yarn run clean +yarn run build + +# Refresh distribution folder +rm -rf dist && mkdir -p dist +mkdir -p ${TYPECHAIN_DIR}/_src +cp -R build/abis/ dist/abis +cp -R build/typechain/contracts/ ${TYPECHAIN_DIR}/_src +cp -R deployments/ dist/deployments +cp -R .openzeppelin/ dist/.openzeppelin + +### Build Typechain bindings + +# Build and create TS declarations +tsc -d ${TYPECHAIN_DIR}/_src/*.ts --outdir ${TYPECHAIN_DIR}/contracts --esModuleInterop +# Copy back sources +cp ${TYPECHAIN_DIR}/_src/*.ts ${TYPECHAIN_DIR}/contracts +# Delete temporary src dir +rm -rf ${TYPECHAIN_DIR}/_src diff --git a/packages/token-distribution/scripts/security b/packages/token-distribution/scripts/security new file mode 100755 index 000000000..90cb4c2f0 --- /dev/null +++ b/packages/token-distribution/scripts/security @@ -0,0 +1,17 @@ +#!/bin/bash + +## Before running: +# This tool requires to have solc installed. +# Ensure that you have the binaries installed by pip3 in your path. +# Install: https://github.com/crytic/slither#how-to-install +# Usage: https://github.com/crytic/slither/wiki/Usage + +mkdir -p reports + +pip3 install --user slither-analyzer && \ +yarn run build && \ + +echo "Analyzing contracts..." +slither . &> reports/analyzer-report.log && \ + +echo "Done!" diff --git a/packages/token-distribution/scripts/test b/packages/token-distribution/scripts/test new file mode 100755 index 000000000..412fc8201 --- /dev/null +++ b/packages/token-distribution/scripts/test @@ -0,0 +1,62 @@ +#!/bin/bash + +set -eo pipefail + +MNEMONIC="myth like bonus scare over problem client lizard pioneer submit female collect" +TESTRPC_PORT=8545 + +### Functions + +evm_running() { + nc -z localhost "$TESTRPC_PORT" +} + +evm_start() { + echo "Starting our own evm instance at port $TESTRPC_PORT" + npx ganache-cli -m "$MNEMONIC" -i 1337 --gasLimit 8000000 --port "$TESTRPC_PORT" > /dev/null & + evm_pid=$! +} + +evm_kill() { + if evm_running; then + echo "Killing evm instance at port $TESTRPC_PORT" + kill -9 $(lsof -i:$TESTRPC_PORT -t) + fi +} + +### Setup evm + +# Gas reporter needs to run in its own evm instance +if [ "$RUN_EVM" = true ]; then + evm_kill + evm_start + sleep 5 +fi + +### Main + +mkdir -p reports + +yarn run compile + +if [ "$RUN_EVM" = true ]; then + # Run using the standalone evm instance + npx hardhat test --network ganache + result=$? +else + # Run using the default evm + npx hardhat test "$@" + result=$? +fi + +### Cleanup + +# Exit error mode so the evm instance always gets killed +set +e +result=0 + +if [ "$RUN_EVM" = true ]; then + evm_kill +fi + +exit $result diff --git a/packages/token-distribution/test/config.ts b/packages/token-distribution/test/config.ts new file mode 100644 index 000000000..fe23b1517 --- /dev/null +++ b/packages/token-distribution/test/config.ts @@ -0,0 +1,101 @@ +import { BigNumber, Contract } from 'ethers' + +import { Account } from './network' + +export enum Revocability { + NotSet, + Enabled, + Disabled, +} + +export interface TokenLockSchedule { + startTime: number + endTime: number + periods: number + revocable: Revocability + releaseStartTime: number + vestingCliffTime: number +} +export interface TokenLockParameters { + owner: string + beneficiary: string + token: string + managedAmount: BigNumber + startTime: number + endTime: number + periods: number + revocable: Revocability + releaseStartTime: number + vestingCliffTime: number +} + +export interface DateRange { + startTime: number + endTime: number +} + +const dateRange = (months: number): DateRange => { + const date = new Date(+new Date() - 120) // set start time for a few seconds before + const newDate = new Date().setMonth(date.getMonth() + months) + return { startTime: Math.round(+date / 1000), endTime: Math.round(+newDate / 1000) } +} + +const moveTime = (time: number, months: number) => { + const date = new Date(time * 1000) + return Math.round(+date.setMonth(date.getMonth() + months) / 1000) +} + +const moveDateRange = (dateRange: DateRange, months: number) => { + return { + startTime: moveTime(dateRange.startTime, months), + endTime: moveTime(dateRange.endTime, months), + } +} + +const createSchedule = ( + startMonths: number, + durationMonths: number, + periods: number, + revocable: Revocability, + releaseStartMonths = 0, + vestingCliffMonths = 0, +) => { + const range = dateRange(durationMonths) + return { + ...moveDateRange(range, startMonths), + periods, + revocable, + releaseStartTime: releaseStartMonths > 0 ? moveTime(range.startTime, releaseStartMonths) : 0, + vestingCliffTime: vestingCliffMonths > 0 ? moveTime(range.startTime, vestingCliffMonths) : 0, + } +} + +export const createScheduleScenarios = (): Array => { + return [ + createSchedule(0, 6, 1, Revocability.Disabled), // 6m lock-up + full release + fully vested + createSchedule(0, 12, 1, Revocability.Disabled), // 12m lock-up + full release + fully vested + createSchedule(12, 12, 12, Revocability.Disabled), // 12m lock-up + 1/12 releases + fully vested + createSchedule(0, 12, 12, Revocability.Disabled), // no-lockup + 1/12 releases + fully vested + createSchedule(-12, 48, 48, Revocability.Enabled, 0), // 1/48 releases + vested + past start + start time override + createSchedule(-12, 48, 48, Revocability.Enabled, 0, 12), // 1/48 releases + vested + past start + start time override + cliff + ] +} + +export const defaultInitArgs = ( + deployer: Account, + beneficiary: Account, + token: Contract, + managedAmount: BigNumber, +): TokenLockParameters => { + const constantData = { + owner: deployer.address, + beneficiary: beneficiary.address, + token: token.address, + managedAmount, + } + + return { + ...createSchedule(0, 6, 1, Revocability.Disabled), + ...constantData, + } +} diff --git a/packages/token-distribution/test/distributor.test.ts b/packages/token-distribution/test/distributor.test.ts new file mode 100644 index 000000000..c9e0b6ac5 --- /dev/null +++ b/packages/token-distribution/test/distributor.test.ts @@ -0,0 +1,201 @@ +import 'hardhat-deploy' +import { deployments } from 'hardhat' +import { expect } from 'chai' +import { GraphTokenDistributor } from '../build/typechain/contracts/GraphTokenDistributor' +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' + +import { Account, getAccounts, getContract, toGRT } from './network' +import { DeployOptions } from 'hardhat-deploy/types' + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + const [deployer] = await getAccounts() + + // Start from a fresh snapshot + await deployments.fixture([]) + + // Deploy token + await deploy('GraphTokenMock', { + from: deployer.address, + args: [toGRT('400000000'), deployer.address], + }) + const grt = await getContract('GraphTokenMock') + + // Deploy distributor + await deploy('GraphTokenDistributor', { + from: deployer.address, + args: [grt.address], + }) + const distributor = await getContract('GraphTokenDistributor') + + return { + grt: grt as GraphTokenMock, + distributor: distributor as GraphTokenDistributor, + } +}) + +describe('GraphTokenDistributor', () => { + let deployer: Account + let beneficiary1: Account + let beneficiary2: Account + + let grt: GraphTokenMock + let distributor: GraphTokenDistributor + + before(async function () { + [deployer, beneficiary1, beneficiary2] = await getAccounts() + }) + + beforeEach(async () => { + ({ grt, distributor } = await setupTest()) + }) + + describe('init', function () { + it('should deploy locked', async function () { + const isLocked = await distributor.locked() + expect(isLocked).eq(true) + }) + }) + + describe('setup beneficiary', function () { + const amount = toGRT('100') + + describe('add', function () { + it('should add tokens to beneficiary', async function () { + const tx = distributor.connect(deployer.signer).addBeneficiaryTokens(beneficiary1.address, amount) + await expect(tx).emit(distributor, 'BeneficiaryUpdated').withArgs(beneficiary1.address, amount) + }) + + it('reject add tokens to beneficiary if not allowed', async function () { + const tx = distributor.connect(beneficiary1.signer).addBeneficiaryTokens(beneficiary1.address, amount) + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + + it('should add tokens to multiple beneficiaries', async function () { + const accounts = [beneficiary1.address, beneficiary2.address] + const amounts = [amount, amount] + + await distributor.connect(deployer.signer).addBeneficiaryTokensMulti(accounts, amounts) + }) + + it('reject add token to multiple beneficiaries if not allowed', async function () { + const accounts = [beneficiary1.address, beneficiary2.address] + const amounts = [amount, amount] + + const tx = distributor.connect(beneficiary1.signer).addBeneficiaryTokensMulti(accounts, amounts) + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + }) + + describe('sub', function () { + it('should remove tokens from beneficiary', async function () { + await distributor.addBeneficiaryTokens(beneficiary1.address, amount) + + const tx = distributor.subBeneficiaryTokens(beneficiary1.address, amount) + await expect(tx).emit(distributor, 'BeneficiaryUpdated').withArgs(beneficiary1.address, toGRT('0')) + }) + + it('reject remove more tokens than available ', async function () { + const tx = distributor.subBeneficiaryTokens(beneficiary1.address, toGRT('1000')) + await expect(tx).revertedWith('SafeMath: subtraction overflow') + }) + }) + }) + + describe('unlocking', function () { + it('should lock', async function () { + const tx = distributor.connect(deployer.signer).setLocked(true) + await expect(tx).emit(distributor, 'LockUpdated').withArgs(true) + expect(await distributor.locked()).eq(true) + }) + + it('should unlock', async function () { + const tx = distributor.connect(deployer.signer).setLocked(false) + await expect(tx).emit(distributor, 'LockUpdated').withArgs(false) + expect(await distributor.locked()).eq(false) + }) + + it('reject unlock if not allowed', async function () { + const tx = distributor.connect(beneficiary1.signer).setLocked(false) + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + }) + + describe('claim', function () { + const totalAmount = toGRT('1000000') + const amount = toGRT('10000') + + beforeEach(async function () { + // Setup + await grt.transfer(distributor.address, totalAmount) + await distributor.connect(deployer.signer).addBeneficiaryTokens(beneficiary1.address, amount) + }) + + it('should claim outstanding token amount', async function () { + await distributor.connect(deployer.signer).setLocked(false) + + const tx = distributor.connect(beneficiary1.signer).claim() + await expect(tx).emit(distributor, 'TokensClaimed').withArgs(beneficiary1.address, beneficiary1.address, amount) + }) + + it('reject claim if locked', async function () { + const tx = distributor.connect(beneficiary1.signer).claim() + await expect(tx).revertedWith('Distributor: Claim is locked') + }) + + it('reject claim if no available tokens', async function () { + await distributor.connect(deployer.signer).setLocked(false) + + const tx = distributor.connect(beneficiary2.signer).claim() + await expect(tx).revertedWith('Distributor: Unavailable funds') + }) + + it('reject claim if beneficiary already claimed all tokens', async function () { + await distributor.connect(deployer.signer).setLocked(false) + + await distributor.connect(beneficiary1.signer).claim() + const tx = distributor.connect(beneficiary1.signer).claim() + await expect(tx).revertedWith('Distributor: Unavailable funds') + }) + }) + + describe('deposit & withdraw', function () { + it('should deposit funds into the distributor', async function () { + const beforeBalance = await grt.balanceOf(distributor.address) + + const amount = toGRT('1000') + await grt.approve(distributor.address, amount) + const tx = distributor.connect(distributor.signer).deposit(amount) + await expect(tx).emit(distributor, 'TokensDeposited').withArgs(deployer.address, amount) + + const afterBalance = await grt.balanceOf(distributor.address) + expect(afterBalance).eq(beforeBalance.add(amount)) + }) + + it('should withdraw tokens from the contract if owner', async function () { + // Setup + const amount = toGRT('1000') + await grt.approve(distributor.address, amount) + await distributor.connect(distributor.signer).deposit(amount) + + const tx = distributor.connect(deployer.signer).withdraw(amount) + await expect(tx).emit(distributor, 'TokensWithdrawn').withArgs(deployer.address, amount) + + const afterBalance = await grt.balanceOf(distributor.address) + expect(afterBalance).eq(0) + }) + + it('reject withdraw tokens from the contract if no balance', async function () { + const amount = toGRT('1000') + const tx = distributor.connect(deployer.signer).withdraw(amount) + await expect(tx).revertedWith('ERC20: transfer amount exceeds balance') + }) + + it('reject withdraw tokens from the contract if not allowed', async function () { + const amount = toGRT('1000') + const tx = distributor.connect(beneficiary1.signer).withdraw(amount) + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + }) +}) diff --git a/packages/token-distribution/test/l1TokenLockTransferTool.test.ts b/packages/token-distribution/test/l1TokenLockTransferTool.test.ts new file mode 100644 index 000000000..75bd26ab8 --- /dev/null +++ b/packages/token-distribution/test/l1TokenLockTransferTool.test.ts @@ -0,0 +1,675 @@ +import { BigNumber, constants, Signer } from 'ethers' +import { deployments, ethers, upgrades } from 'hardhat' +import { expect } from 'chai' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenLockManager } from '../build/typechain/contracts/GraphTokenLockManager' +import { GraphTokenLockWallet } from '../build/typechain/contracts/GraphTokenLockWallet' +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { L1GraphTokenLockTransferTool } from '../build/typechain/contracts/L1GraphTokenLockTransferTool' +import { L1TokenGatewayMock } from '../build/typechain/contracts/L1TokenGatewayMock' +import { StakingMock } from '../build/typechain/contracts/StakingMock' + +import { L1GraphTokenLockTransferTool__factory } from '../build/typechain/contracts/factories/L1GraphTokenLockTransferTool__factory' +import { Staking__factory } from '@graphprotocol/contracts/dist/types/factories/Staking__factory' + +import { Account, getAccounts, getContract, toBN, toGRT } from './network' +import { defaultAbiCoder, hexValue, keccak256, parseEther } from 'ethers/lib/utils' +import { defaultInitArgs, Revocability, TokenLockParameters } from './config' +import { advanceTimeAndBlock } from './network' +import { DeployOptions } from 'hardhat-deploy/types' + +const { AddressZero } = constants + +async function impersonateAccount(address: string): Promise { + await ethers.provider.send('hardhat_impersonateAccount', [address]) + return ethers.getSigner(address) +} + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + const [deployer, , , , l2LockImplementationMock] = await getAccounts() + + // Start from a fresh snapshot + await deployments.fixture([]) + + // Deploy token + await deploy('GraphTokenMock', { + from: deployer.address, + args: [toGRT('1000000000'), deployer.address], + }) + const grt = await getContract('GraphTokenMock') + + // Deploy token lock masterCopy + await deploy('GraphTokenLockWallet', { + from: deployer.address, + }) + const tokenLockWallet = await getContract('GraphTokenLockWallet') + + // Deploy token lock manager + await deploy('GraphTokenLockManager', { + from: deployer.address, + args: [grt.address, tokenLockWallet.address], + }) + const tokenLockManager = await getContract('GraphTokenLockManager') + + // Protocol contracts + await deploy('StakingMock', { from: deployer.address, args: [grt.address] }) + const staking = await getContract('StakingMock') + + await deploy('L1TokenGatewayMock', { from: deployer.address, args: [] }) + const gateway = await getContract('L1TokenGatewayMock') + + // Deploy transfer tool using a proxy + const transferToolFactory = await ethers.getContractFactory('L1GraphTokenLockTransferTool') + const transferTool = (await upgrades.deployProxy(transferToolFactory, [deployer.address], { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [grt.address, l2LockImplementationMock.address, gateway.address, staking.address], + })) as L1GraphTokenLockTransferTool + + // Fund the manager contract + await grt.connect(deployer.signer).transfer(tokenLockManager.address, toGRT('100000000')) + + return { + grt: grt as GraphTokenMock, + staking: staking as StakingMock, + // tokenLock: tokenLockWallet as GraphTokenLockWallet, + tokenLockManager: tokenLockManager as GraphTokenLockManager, + gateway: gateway as L1TokenGatewayMock, + transferTool: transferTool, + } +}) + +async function authProtocolFunctions( + tokenLockManager: GraphTokenLockManager, + stakingAddress: string, + transferToolAddress: string, +) { + await tokenLockManager.setAuthFunctionCall('stake(uint256)', stakingAddress) + await tokenLockManager.setAuthFunctionCall('unstake(uint256)', stakingAddress) + await tokenLockManager.setAuthFunctionCall('withdraw()', stakingAddress) + await tokenLockManager.setAuthFunctionCall( + 'depositToL2Locked(uint256,address,uint256,uint256,uint256)', + transferToolAddress, + ) + await tokenLockManager.setAuthFunctionCall('withdrawETH(address,uint256)', transferToolAddress) + await tokenLockManager.setAuthFunctionCall('setL2WalletAddressManually(address)', transferToolAddress) +} + +// -- Tests -- + +const maxSubmissionCost = toBN('10000') +const maxGas = toBN('1000000') +const gasPrice = toBN('10') +const ticketValue = maxSubmissionCost.add(maxGas.mul(gasPrice)) + +describe('L1GraphTokenLockTransferTool', () => { + let deployer: Account + let beneficiary: Account + let hacker: Account + let l2ManagerMock: Account + let l2LockImplementationMock: Account + let l2Owner: Account + let l2Beneficiary: Account + + let grt: GraphTokenMock + let tokenLock: GraphTokenLockWallet + let tokenLockManager: GraphTokenLockManager + let staking: StakingMock + let gateway: L1TokenGatewayMock + let transferTool: L1GraphTokenLockTransferTool + let lockAsTransferTool: L1GraphTokenLockTransferTool + + let initArgs: TokenLockParameters + + const initWithArgs = async (args: TokenLockParameters): Promise => { + const tx = await tokenLockManager.createTokenLockWallet( + args.owner, + args.beneficiary, + args.managedAmount, + args.startTime, + args.endTime, + args.periods, + args.releaseStartTime, + args.vestingCliffTime, + args.revocable, + ) + const receipt = await tx.wait() + const contractAddress = receipt.events[0].args['proxy'] + return ethers.getContractAt('GraphTokenLockWallet', contractAddress) as Promise + } + + before(async function () { + [deployer, beneficiary, hacker, l2ManagerMock, l2LockImplementationMock, l2Owner, l2Beneficiary] + = await getAccounts() + }) + + beforeEach(async () => { + ({ grt, tokenLockManager, staking, gateway, transferTool } = await setupTest()) + + // Setup authorized functions in Manager + await authProtocolFunctions(tokenLockManager, staking.address, transferTool.address) + + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + tokenLock = await initWithArgs(initArgs) + + // Use the tokenLock contract as if it were the L1GraphTokenLockTransferTool contract + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + + // Add the transfer tool and staking contracts as token destinations + await tokenLockManager.addTokenDestination(transferTool.address) + await tokenLockManager.addTokenDestination(staking.address) + + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + await transferTool.setL2LockManager(tokenLockManager.address, l2ManagerMock.address) + await transferTool.setL2WalletOwner(deployer.address, l2Owner.address) + }) + + describe('Upgrades', function () { + it('should be upgradeable', async function () { + const transferToolFactory = await ethers.getContractFactory('L1GraphTokenLockTransferTool') + transferTool = (await upgrades.upgradeProxy(transferTool.address, transferToolFactory, { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [beneficiary.address, l2LockImplementationMock.address, gateway.address, staking.address], + })) as L1GraphTokenLockTransferTool + expect(await transferTool.graphToken()).to.eq(beneficiary.address) + transferTool = (await upgrades.upgradeProxy(transferTool.address, transferToolFactory, { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [grt.address, l2LockImplementationMock.address, gateway.address, staking.address], + })) as L1GraphTokenLockTransferTool + expect(await transferTool.graphToken()).to.eq(grt.address) + }) + }) + describe('Registering L2 managers', function () { + it('rejects calls from non-owners', async function () { + const tx = transferTool.connect(beneficiary.signer).setL2LockManager(beneficiary.address, hacker.address) + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + it('sets the L2 manager for an L1 manager', async function () { + await transferTool.setL2LockManager(tokenLockManager.address, l2ManagerMock.address) + expect(await transferTool.l2LockManager(tokenLockManager.address)).to.eq(l2ManagerMock.address) + }) + }) + describe('Registering L2 wallet owners', function () { + it('rejects calls from non-owners', async function () { + const tx = transferTool.connect(beneficiary.signer).setL2WalletOwner(beneficiary.address, hacker.address) + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + it('sets the L2 wallet owner for an L1 wallet owner', async function () { + await transferTool.setL2WalletOwner(hacker.address, l2Owner.address) + expect(await transferTool.l2WalletOwner(hacker.address)).to.eq(l2Owner.address) + }) + }) + describe('Depositing, withdrawing and pulling ETH', function () { + it('allows someone to deposit eth into their token lock account', async function () { + const tx = transferTool.connect(beneficiary.signer).depositETH(tokenLock.address, { value: ticketValue }) + await expect(tx).emit(transferTool, 'ETHDeposited').withArgs(tokenLock.address, ticketValue) + expect(await ethers.provider.getBalance(transferTool.address)).to.eq(ticketValue) + expect(await transferTool.tokenLockETHBalances(tokenLock.address)).to.eq(ticketValue) + }) + it('adds to the token lock ETH balance when called a second time', async function () { + await transferTool.connect(beneficiary.signer).depositETH(tokenLock.address, { value: ticketValue }) + expect(await transferTool.tokenLockETHBalances(tokenLock.address)).to.eq(ticketValue) + await transferTool.connect(beneficiary.signer).depositETH(tokenLock.address, { value: ticketValue }) + expect(await transferTool.tokenLockETHBalances(tokenLock.address)).to.eq(ticketValue.mul(2)) + }) + it('allows someone to withdraw eth from their token lock account', async function () { + // We'll withdraw to the "hacker" account so that we don't need to subtract gas + await transferTool.connect(beneficiary.signer).depositETH(tokenLock.address, { value: ticketValue }) + const prevBalance = await ethers.provider.getBalance(hacker.address) + const tx = lockAsTransferTool.connect(beneficiary.signer).withdrawETH(hacker.address, ticketValue) + await expect(tx).emit(transferTool, 'ETHWithdrawn').withArgs(tokenLock.address, hacker.address, ticketValue) + expect(await ethers.provider.getBalance(transferTool.address)).to.eq(0) + expect(await transferTool.tokenLockETHBalances(tokenLock.address)).to.eq(0) + expect(await ethers.provider.getBalance(hacker.address)).to.eq(prevBalance.add(ticketValue)) + }) + it('fails when trying to withdraw 0 eth from a token lock account', async function () { + // We'll withdraw to the "hacker" account so that we don't need to subtract gas + const tx = lockAsTransferTool.connect(beneficiary.signer).withdrawETH(hacker.address, BigNumber.from(0)) + await expect(tx).revertedWith('INVALID_AMOUNT') + }) + it('allows the Staking contract to pull ETH from the token lock account', async function () { + await transferTool.connect(beneficiary.signer).depositETH(tokenLock.address, { value: ticketValue }) + const prevBalance = parseEther('1') + await ethers.provider.send('hardhat_setBalance', [staking.address, hexValue(prevBalance)]) + const stakingSigner = await impersonateAccount(staking.address) + const tx = transferTool.connect(stakingSigner).pullETH(tokenLock.address, ticketValue) + const receipt = await (await tx).wait() + await expect(tx).emit(transferTool, 'ETHPulled').withArgs(tokenLock.address, ticketValue) + expect(await ethers.provider.getBalance(transferTool.address)).to.eq(0) + expect(await transferTool.tokenLockETHBalances(tokenLock.address)).to.eq(0) + expect(await ethers.provider.getBalance(staking.address)).to.eq( + prevBalance.add(ticketValue).sub(receipt.gasUsed.mul(receipt.effectiveGasPrice)), + ) + }) + it('does not allow someone else to pull ETH from the token lock account', async function () { + await transferTool.connect(beneficiary.signer).depositETH(tokenLock.address, { value: ticketValue }) + const tx = transferTool.connect(hacker.signer).pullETH(tokenLock.address, ticketValue) + await expect(tx).revertedWith('ONLY_STAKING') + }) + }) + describe('Depositing to L2', function () { + it('rejects calls if the manager is not registered', async function () { + await transferTool.setL2LockManager(tokenLockManager.address, AddressZero) + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('10000000'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('INVALID_MANAGER') + }) + it('rejects calls if the L2 owner for the wallet is not set', async function () { + const amountToSend = toGRT('1000') + // "hacker" will be the owner here, and it does not have an L2 owner set + initArgs = defaultInitArgs(hacker, beneficiary, grt, toGRT('2000000')) + tokenLock = await initWithArgs(initArgs) + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).acceptLock() + + // Good hacker pays for the gas + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue }) + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('L2_OWNER_NOT_SET') + }) + + it('rejects calls from wallets that have the wrong token address', async function () { + // WalletMock constructor args are: target, token, manager, isInitialized, isAccepted + await deployments.deploy('WalletMock', { + from: deployer.address, + args: [ + transferTool.address, + '0x5c946740441C12510a167B447B7dE565C20b9E3C', + tokenLockManager.address, + true, + true, + ], + }) + const wrongTokenWallet = await getContract('WalletMock') + const walletAsTransferTool = L1GraphTokenLockTransferTool__factory.connect( + wrongTokenWallet.address, + deployer.signer, + ) + + const tx = walletAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('10000000'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('INVALID_TOKEN') + }) + + it('rejects calls from a wallet that is not initialized', async function () { + // WalletMock constructor args are: target, token, manager, isInitialized, isAccepted + await deployments.deploy('WalletMock', { + from: deployer.address, + args: [transferTool.address, grt.address, tokenLockManager.address, false, true], + }) + const uninitWallet = await getContract('WalletMock') + const walletAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(uninitWallet.address, deployer.signer) + + const tx = walletAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('10000000'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('!INITIALIZED') + }) + it('rejects calls from a revocable wallet', async function () { + initArgs.revocable = Revocability.Enabled + tokenLock = await initWithArgs(initArgs) + + await tokenLock.connect(beneficiary.signer).acceptLock() + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).approveProtocol() + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('10000000'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('REVOCABLE') + }) + it('rejects calls if the wallet does not have enough tokens', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('35000001'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('INSUFFICIENT_BALANCE') + }) + it('rejects calls if the amount is zero', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('0'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('ZERO_AMOUNT') + }) + it('rejects calls if the wallet does not have a sufficient ETH balance previously deposited', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('35000000'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('INSUFFICIENT_ETH_BALANCE') + + // Try again but with an ETH balance that is insufficient by 1 wei + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue.sub(1) }) + const tx2 = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('35000000'), l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx2).revertedWith('INSUFFICIENT_ETH_BALANCE') + }) + it('rejects calls if the L2 beneficiary is zero', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('10000000'), AddressZero, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('INVALID_BENEFICIARY_ZERO') + }) + it('rejects calls if the L2 beneficiary is a contract', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(toGRT('10000000'), staking.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).revertedWith('INVALID_BENEFICIARY_CONTRACT') + }) + it('sends tokens and a callhook to the L2 manager registered for the wallet', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + const amountToSend = toGRT('1000') + + const expectedWalletData = defaultAbiCoder.encode( + ['tuple(address,address,address,uint256,uint256,uint256)'], + [ + [ + tokenLock.address, + l2Owner.address, + l2Beneficiary.address, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + const expectedL2Address = await transferTool['getDeploymentAddress(bytes32,address,address)']( + keccak256(expectedWalletData), + l2LockImplementationMock.address, + l2ManagerMock.address, + ) + + const expectedOutboundCalldata = await gateway.getOutboundCalldata( + grt.address, + transferTool.address, + l2ManagerMock.address, + amountToSend, + expectedWalletData, + ) + + // Good hacker pays for the gas + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue }) + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx) + .emit(transferTool, 'LockedFundsSentToL2') + .withArgs( + lockAsTransferTool.address, + expectedL2Address, + tokenLockManager.address, + l2ManagerMock.address, + amountToSend, + ) + // Check that the right amount of ETH has been pulled from the token lock's account + await expect(tx) + .emit(transferTool, 'ETHPulled') + .withArgs(tokenLock.address, maxGas.mul(gasPrice).add(maxSubmissionCost)) + await expect(tx).emit(transferTool, 'L2BeneficiarySet').withArgs(tokenLock.address, l2Beneficiary.address) + // Check the events emitted from the mock gateway + await expect(tx) + .emit(gateway, 'FakeTxToL2') + .withArgs(transferTool.address, ticketValue, maxGas, gasPrice, maxSubmissionCost, expectedOutboundCalldata) + // and check that the right amount of funds have been pulled from the token lock + expect(await grt.balanceOf(tokenLock.address)).to.equal(initArgs.managedAmount.sub(amountToSend)) + }) + it('uses the previous L2 wallet address if called for a second time', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + const amountToSend = toGRT('1000') + + const expectedWalletData = defaultAbiCoder.encode( + ['tuple(address,address,address,uint256,uint256,uint256)'], + [ + [ + tokenLock.address, + l2Owner.address, + l2Beneficiary.address, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + const expectedL2Address = await transferTool['getDeploymentAddress(bytes32,address,address)']( + keccak256(expectedWalletData), + l2LockImplementationMock.address, + l2ManagerMock.address, + ) + + const expectedOutboundCalldata = await gateway.getOutboundCalldata( + grt.address, + transferTool.address, + l2ManagerMock.address, + amountToSend, + expectedWalletData, + ) + + // Good hacker pays for the gas + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue.mul(2) }) + await lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + // Call again + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx) + .emit(transferTool, 'LockedFundsSentToL2') + .withArgs( + lockAsTransferTool.address, + expectedL2Address, + tokenLockManager.address, + l2ManagerMock.address, + amountToSend, + ) + await expect(tx).not.emit(transferTool, 'L2BeneficiarySet') + // Check the events emitted from the mock gateway + await expect(tx) + .emit(gateway, 'FakeTxToL2') + .withArgs(transferTool.address, ticketValue, maxGas, gasPrice, maxSubmissionCost, expectedOutboundCalldata) + // and check that the right amount of funds have been pulled from the token lock + expect(await grt.balanceOf(tokenLock.address)).to.equal(initArgs.managedAmount.sub(amountToSend.mul(2))) + }) + it('accepts calls from a wallet that has funds staked in the protocol', async function () { + // Use the tokenLock contract as if it were the Staking contract + const lockAsStaking = Staking__factory.connect(tokenLock.address, deployer.signer) + const stakeAmount = toGRT('1000') + // Stake some funds + await lockAsStaking.connect(beneficiary.signer).stake(stakeAmount) + + await tokenLock.connect(beneficiary.signer).acceptLock() + const amountToSend = toGRT('1000') + + const expectedWalletData = defaultAbiCoder.encode( + ['tuple(address,address,address,uint256,uint256,uint256)'], + [ + [ + tokenLock.address, + l2Owner.address, + l2Beneficiary.address, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + const expectedL2Address = await transferTool['getDeploymentAddress(bytes32,address,address)']( + keccak256(expectedWalletData), + l2LockImplementationMock.address, + l2ManagerMock.address, + ) + + const expectedOutboundCalldata = await gateway.getOutboundCalldata( + grt.address, + transferTool.address, + l2ManagerMock.address, + amountToSend, + expectedWalletData, + ) + + // Good hacker pays for the gas + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue }) + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx) + .emit(transferTool, 'LockedFundsSentToL2') + .withArgs( + lockAsTransferTool.address, + expectedL2Address, + tokenLockManager.address, + l2ManagerMock.address, + amountToSend, + ) + // Check the events emitted from the mock gateway + await expect(tx) + .emit(gateway, 'FakeTxToL2') + .withArgs(transferTool.address, ticketValue, maxGas, gasPrice, maxSubmissionCost, expectedOutboundCalldata) + // and check that the right amount of funds have been pulled from the token lock + expect(await grt.balanceOf(tokenLock.address)).to.equal(initArgs.managedAmount.sub(amountToSend).sub(stakeAmount)) + }) + it('rejects calling a second time if the l2 beneficiary is different', async function () { + await tokenLock.connect(beneficiary.signer).acceptLock() + const amountToSend = toGRT('1000') + + // Good hacker pays for the gas + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue }) + await lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + // Call again + await expect( + lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Owner.address, maxGas, gasPrice, maxSubmissionCost), + ).to.be.revertedWith('INVALID_BENEFICIARY') + }) + it('rejects first calls from a token lock that is fully-vested', async function () { + initArgs.endTime = Math.round(+new Date(+new Date() - 120) / 1000) + initArgs.startTime = initArgs.endTime - 1000 + + tokenLock = await initWithArgs(initArgs) + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).acceptLock() + await tokenLock.connect(beneficiary.signer).approveProtocol() + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue }) + const amountToSend = toGRT('1000') + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).to.be.revertedWith('FULLY_VESTED_USE_MANUAL_ADDRESS') + }) + it('accepts calls from a fully-vested wallet if it had been called before', async function () { + // End time two minutes in the future + initArgs.endTime = Math.round(+new Date(+new Date() + 120000) / 1000) + initArgs.startTime = initArgs.endTime - 1000 + + tokenLock = await initWithArgs(initArgs) + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).acceptLock() + await tokenLock.connect(beneficiary.signer).approveProtocol() + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue.mul(2) }) + const amountToSend = toGRT('1000') + await lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + + await advanceTimeAndBlock(200) + const tx = lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + await expect(tx).emit(transferTool, 'LockedFundsSentToL2') + }) + }) + describe('Setting an L2 wallet address manually', function () { + it('sets the l2WalletAddress for a token lock that is fully-vested', async function () { + initArgs.endTime = Math.round(+new Date(+new Date() - 120) / 1000) + initArgs.startTime = initArgs.endTime - 1000 + + tokenLock = await initWithArgs(initArgs) + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).acceptLock() + + const tx = await lockAsTransferTool.connect(beneficiary.signer).setL2WalletAddressManually(l2Beneficiary.address) + await expect(tx).emit(transferTool, 'L2WalletAddressSet').withArgs(tokenLock.address, l2Beneficiary.address) + expect(await transferTool.l2WalletAddress(tokenLock.address)).to.equal(l2Beneficiary.address) + }) + it('reverts for a wallet that is not fully-vested', async function () { + await expect( + lockAsTransferTool.connect(beneficiary.signer).setL2WalletAddressManually(l2Beneficiary.address), + ).to.be.revertedWith('NOT_FULLY_VESTED') + }) + it('reverts for a wallet that has already had the address set', async function () { + initArgs.endTime = Math.round(+new Date(+new Date() - 120) / 1000) + initArgs.startTime = initArgs.endTime - 1000 + + tokenLock = await initWithArgs(initArgs) + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).acceptLock() + await lockAsTransferTool.connect(beneficiary.signer).setL2WalletAddressManually(l2Beneficiary.address) + + await expect( + lockAsTransferTool.connect(beneficiary.signer).setL2WalletAddressManually(l2Beneficiary.address), + ).to.be.revertedWith('L2_WALLET_ALREADY_SET') + }) + it('reverts for a wallet that has previously called depositToL2Locked', async function () { + // End time two minutes in the future + initArgs.endTime = Math.round(+new Date(+new Date() + 120000) / 1000) + initArgs.startTime = initArgs.endTime - 1000 + + tokenLock = await initWithArgs(initArgs) + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).acceptLock() + await tokenLock.connect(beneficiary.signer).approveProtocol() + const amountToSend = toGRT('1000') + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue }) + await lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost) + + await advanceTimeAndBlock(200) + await expect( + lockAsTransferTool.connect(beneficiary.signer).setL2WalletAddressManually(l2Beneficiary.address), + ).to.be.revertedWith('L2_WALLET_ALREADY_SET') + }) + it('prevents subsequent calls to depositToL2Locked from working', async function () { + initArgs.endTime = Math.round(+new Date(+new Date() - 120) / 1000) + initArgs.startTime = initArgs.endTime - 1000 + + tokenLock = await initWithArgs(initArgs) + lockAsTransferTool = L1GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + await tokenLock.connect(beneficiary.signer).acceptLock() + await tokenLock.connect(beneficiary.signer).approveProtocol() + const amountToSend = toGRT('1000') + await transferTool.connect(hacker.signer).depositETH(tokenLock.address, { value: ticketValue }) + + await lockAsTransferTool.connect(beneficiary.signer).setL2WalletAddressManually(l2Beneficiary.address) + + await expect( + lockAsTransferTool + .connect(beneficiary.signer) + .depositToL2Locked(amountToSend, l2Beneficiary.address, maxGas, gasPrice, maxSubmissionCost), + ).to.be.revertedWith('CANT_DEPOSIT_TO_MANUAL_ADDRESS') + }) + }) +}) diff --git a/packages/token-distribution/test/l2TokenLockManager.test.ts b/packages/token-distribution/test/l2TokenLockManager.test.ts new file mode 100644 index 000000000..b093773b9 --- /dev/null +++ b/packages/token-distribution/test/l2TokenLockManager.test.ts @@ -0,0 +1,460 @@ +import { constants, Wallet } from 'ethers' +import { deployments, ethers } from 'hardhat' +import { expect } from 'chai' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { L2GraphTokenLockManager } from '../build/typechain/contracts/L2GraphTokenLockManager' +import { L2GraphTokenLockWallet } from '../build/typechain/contracts/L2GraphTokenLockWallet' +import { Staking__factory } from '@graphprotocol/contracts/dist/types/factories/Staking__factory' +import { StakingMock } from '../build/typechain/contracts/StakingMock' + +import { Account, advanceTimeAndBlock, getAccounts, getContract, toGRT } from './network' +import { defaultAbiCoder, keccak256 } from 'ethers/lib/utils' +import { defaultInitArgs, Revocability, TokenLockParameters } from './config' +import { DeployOptions } from 'hardhat-deploy/types' +import { Staking } from '@graphprotocol/contracts' + +const { AddressZero } = constants + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + const [deployer, , l1TransferToolMock, gateway] = await getAccounts() + + // Start from a fresh snapshot + await deployments.fixture([]) + + // Deploy token + await deploy('GraphTokenMock', { + from: deployer.address, + args: [toGRT('1000000000'), deployer.address], + }) + const grt = await getContract('GraphTokenMock') + + // Deploy token lock masterCopy + await deploy('L2GraphTokenLockWallet', { + from: deployer.address, + }) + const tokenLockWallet = await getContract('L2GraphTokenLockWallet') + + // Deploy token lock manager + await deploy('L2GraphTokenLockManager', { + from: deployer.address, + args: [grt.address, tokenLockWallet.address, gateway.address, l1TransferToolMock.address], + }) + const tokenLockManager = await getContract('L2GraphTokenLockManager') + + // Protocol contracts + await deploy('StakingMock', { from: deployer.address, args: [grt.address] }) + const staking = await getContract('StakingMock') + + // Fund the manager contract + await grt.connect(deployer.signer).transfer(tokenLockManager.address, toGRT('100000000')) + + return { + grt: grt as GraphTokenMock, + staking: staking as StakingMock, + tokenLockImplementation: tokenLockWallet as L2GraphTokenLockWallet, + tokenLockManager: tokenLockManager as L2GraphTokenLockManager, + } +}) + +async function authProtocolFunctions(tokenLockManager: L2GraphTokenLockManager, stakingAddress: string) { + await tokenLockManager.setAuthFunctionCall('stake(uint256)', stakingAddress) + await tokenLockManager.setAuthFunctionCall('unstake(uint256)', stakingAddress) + await tokenLockManager.setAuthFunctionCall('withdraw()', stakingAddress) +} + +describe('L2GraphTokenLockManager', () => { + let deployer: Account + let beneficiary: Account + let l1TransferToolMock: Account + let gateway: Account + let l1TokenLock: Account + + let grt: GraphTokenMock + let tokenLock: L2GraphTokenLockWallet + let tokenLockImplementation: L2GraphTokenLockWallet + let tokenLockManager: L2GraphTokenLockManager + let staking: StakingMock + let lockAsStaking: Staking + + let initArgs: TokenLockParameters + + const initWithArgs = async (args: TokenLockParameters): Promise => { + const tx = await tokenLockManager.createTokenLockWallet( + args.owner, + args.beneficiary, + args.managedAmount, + args.startTime, + args.endTime, + args.periods, + args.releaseStartTime, + args.vestingCliffTime, + args.revocable, + ) + const receipt = await tx.wait() + const contractAddress = receipt.events[0].args['proxy'] + return ethers.getContractAt('L2GraphTokenLockWallet', contractAddress) as Promise + } + + before(async function () { + [deployer, beneficiary, l1TransferToolMock, gateway, l1TokenLock] = await getAccounts() + }) + + beforeEach(async () => { + ({ grt, tokenLockManager, staking, tokenLockImplementation } = await setupTest()) + + // Setup authorized functions in Manager + await authProtocolFunctions(tokenLockManager, staking.address) + + // Add the staking contract as token destination + await tokenLockManager.addTokenDestination(staking.address) + }) + + describe('TokenLockManager standard behavior', function () { + it('reverts if initialized with empty token', async function () { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + + const d = deploy('L2GraphTokenLockManager', { + from: deployer.address, + args: [ + AddressZero, + Wallet.createRandom().address, + Wallet.createRandom().address, + Wallet.createRandom().address, + ], + }) + await expect(d).revertedWith('Token cannot be zero') + }) + + it('should set the master copy', async function () { + const address = Wallet.createRandom().address + const tx = tokenLockManager.setMasterCopy(address) + await expect(tx).emit(tokenLockManager, 'MasterCopyUpdated').withArgs(address) + }) + + it('reverts if setting the master copy to zero address', async function () { + const tx = tokenLockManager.setMasterCopy(AddressZero) + await expect(tx).revertedWith('MasterCopy cannot be zero') + }) + + it('should add a token destination', async function () { + const address = Wallet.createRandom().address + + expect(await tokenLockManager.isTokenDestination(address)).eq(false) + const tx = tokenLockManager.addTokenDestination(address) + await expect(tx).emit(tokenLockManager, 'TokenDestinationAllowed').withArgs(address, true) + expect(await tokenLockManager.isTokenDestination(address)).eq(true) + }) + + it('reverts when adding a token destination with zero address', async function () { + const tx = tokenLockManager.addTokenDestination(AddressZero) + await expect(tx).revertedWith('Destination cannot be zero') + }) + + it('creates a token lock wallet that can participate in the protocol', async function () { + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + tokenLock = await initWithArgs(initArgs) + + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + + // Check that the token lock wallet was created with the correct parameters + expect(await tokenLock.owner()).eq(initArgs.owner) + expect(await tokenLock.beneficiary()).eq(initArgs.beneficiary) + expect(await tokenLock.managedAmount()).eq(initArgs.managedAmount) + expect(await tokenLock.startTime()).eq(initArgs.startTime) + expect(await tokenLock.endTime()).eq(initArgs.endTime) + expect(await tokenLock.periods()).eq(initArgs.periods) + expect(await tokenLock.releaseStartTime()).eq(initArgs.releaseStartTime) + expect(await tokenLock.vestingCliffTime()).eq(initArgs.vestingCliffTime) + expect(await tokenLock.revocable()).eq(initArgs.revocable) + expect(await tokenLock.isAccepted()).eq(false) + + expect(await grt.balanceOf(tokenLock.address)).eq(initArgs.managedAmount) + + // Stake in the protocol using the lock as a Staking contract + const amount = toGRT('10000000') + + lockAsStaking = Staking__factory.connect(tokenLock.address, deployer.signer) + await lockAsStaking.connect(beneficiary.signer).stake(amount) + + // Check that the staking contract received the tokens + expect(await grt.balanceOf(staking.address)).eq(amount) + // Check the token lock wallet balance + expect(await grt.balanceOf(tokenLock.address)).eq(initArgs.managedAmount.sub(amount)) + }) + }) + describe('onTokenTransfer', function () { + it('receives tokens and creates a new token lock with the received parameters', async function () { + // ABI-encoded callhook data + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + const walletDataType = 'tuple(address,address,address,uint256,uint256,uint256)' + const data = defaultAbiCoder.encode( + [walletDataType], + [ + [ + l1TokenLock.address, + initArgs.owner, + initArgs.beneficiary, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + const walletData = { + l1Address: l1TokenLock.address, + owner: initArgs.owner, + beneficiary: initArgs.beneficiary, + managedAmount: initArgs.managedAmount, + startTime: initArgs.startTime, + endTime: initArgs.endTime, + } + + const expectedL2Address = await tokenLockManager['getDeploymentAddress(bytes32,address,address)']( + keccak256(data), + tokenLockImplementation.address, + tokenLockManager.address, + ) + + // Assume part of the managed amount were used in L1, so we don't get all of it + const transferredAmount = initArgs.managedAmount.sub(toGRT('100000')) + + const expectedInitData = tokenLockImplementation.interface.encodeFunctionData('initializeFromL1', [ + tokenLockManager.address, + grt.address, + walletData, + ]) + const expectedInitHash = keccak256(expectedInitData) + + // Call onTokenTransfer from the gateway: + const tx = tokenLockManager + .connect(gateway.signer) + .onTokenTransfer(l1TransferToolMock.address, transferredAmount, data) + + await expect(tx) + .emit(tokenLockManager, 'TokenLockCreatedFromL1') + .withArgs( + expectedL2Address, + expectedInitHash, + walletData.beneficiary, + walletData.managedAmount, + walletData.startTime, + walletData.endTime, + walletData.l1Address, + ) + + // Check that the token lock wallet was created with the correct parameters + const tokenLock = (await ethers.getContractAt( + 'L2GraphTokenLockWallet', + expectedL2Address, + deployer.signer, + )) as L2GraphTokenLockWallet + expect(await tokenLock.owner()).eq(initArgs.owner) + expect(await tokenLock.beneficiary()).eq(initArgs.beneficiary) + expect(await tokenLock.managedAmount()).eq(initArgs.managedAmount) + expect(await tokenLock.startTime()).eq(initArgs.startTime) + expect(await tokenLock.endTime()).eq(initArgs.endTime) + expect(await tokenLock.periods()).eq(1) + expect(await tokenLock.releaseStartTime()).eq(initArgs.endTime) + expect(await tokenLock.vestingCliffTime()).eq(0) + expect(await tokenLock.revocable()).eq(Revocability.Disabled) + expect(await grt.balanceOf(tokenLock.address)).eq(transferredAmount) + expect(await tokenLock.isAccepted()).eq(true) + + // The mapping for L1 address to L2 address should be set correctly + expect(await tokenLockManager.l1WalletToL2Wallet(l1TokenLock.address)).eq(expectedL2Address) + // And same for L2 address to L1 address + expect(await tokenLockManager.l2WalletToL1Wallet(expectedL2Address)).eq(l1TokenLock.address) + }) + it('sends the tokens to an already created wallet', async function () { + // ABI-encoded callhook data + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + const walletDataType = 'tuple(address,address,address,uint256,uint256,uint256)' + const data = defaultAbiCoder.encode( + [walletDataType], + [ + [ + l1TokenLock.address, + initArgs.owner, + initArgs.beneficiary, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + const walletData = { + l1Address: l1TokenLock.address, + owner: initArgs.owner, + beneficiary: initArgs.beneficiary, + managedAmount: initArgs.managedAmount, + startTime: initArgs.startTime, + endTime: initArgs.endTime, + } + + const expectedL2Address = await tokenLockManager['getDeploymentAddress(bytes32,address,address)']( + keccak256(data), + tokenLockImplementation.address, + tokenLockManager.address, + ) + + // Assume part of the managed amount were used in L1, so we don't get all of it + const transferredAmount = initArgs.managedAmount.sub(toGRT('100000')) + + const expectedInitData = tokenLockImplementation.interface.encodeFunctionData('initializeFromL1', [ + tokenLockManager.address, + grt.address, + walletData, + ]) + const expectedInitHash = keccak256(expectedInitData) + + // Call onTokenTransfer from the gateway: + const tx = tokenLockManager + .connect(gateway.signer) + .onTokenTransfer(l1TransferToolMock.address, transferredAmount, data) + + await expect(tx) + .emit(tokenLockManager, 'TokenLockCreatedFromL1') + .withArgs( + expectedL2Address, + expectedInitHash, + walletData.beneficiary, + walletData.managedAmount, + walletData.startTime, + walletData.endTime, + walletData.l1Address, + ) + + // Check that the token lock wallet was created with the correct parameters + const tokenLock = (await ethers.getContractAt( + 'L2GraphTokenLockWallet', + expectedL2Address, + deployer.signer, + )) as L2GraphTokenLockWallet + expect(await grt.balanceOf(tokenLock.address)).eq(transferredAmount) + + // Call onTokenTransfer from the gateway again: + const tx2 = tokenLockManager + .connect(gateway.signer) + .onTokenTransfer(l1TransferToolMock.address, transferredAmount, data) + // This tx should not emit a TokenLockCreatedFromL1 event + await expect(tx2).to.not.emit(tokenLockManager, 'TokenLockCreatedFromL1') + // But it should transfer the tokens to the token lock wallet + expect(await grt.balanceOf(tokenLock.address)).eq(transferredAmount.mul(2)) + }) + it('creates a wallet that can participate in the protocol', async function () { + // ABI-encoded callhook data + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + const walletDataType = 'tuple(address,address,address,uint256,uint256,uint256)' + const data = defaultAbiCoder.encode( + [walletDataType], + [ + [ + l1TokenLock.address, + initArgs.owner, + initArgs.beneficiary, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + + const expectedL2Address = await tokenLockManager['getDeploymentAddress(bytes32,address,address)']( + keccak256(data), + tokenLockImplementation.address, + tokenLockManager.address, + ) + + // Assume part of the managed amount were used in L1, so we don't get all of it + const transferredAmount = initArgs.managedAmount.sub(toGRT('100000')) + + // Call onTokenTransfer from the gateway: + await tokenLockManager + .connect(gateway.signer) + .onTokenTransfer(l1TransferToolMock.address, transferredAmount, data) + + // Check that the token lock wallet was created with the correct parameters + const tokenLock = (await ethers.getContractAt( + 'L2GraphTokenLockWallet', + expectedL2Address, + deployer.signer, + )) as L2GraphTokenLockWallet + + // Approve the protocol + await tokenLock.connect(beneficiary.signer).approveProtocol() + + // And the created wallet should be able to participate in the protocol + // Stake in the protocol using the lock as a Staking contract + const amount = toGRT('100000') + + const lockAsStaking = Staking__factory.connect(tokenLock.address, deployer.signer) + await lockAsStaking.connect(beneficiary.signer).stake(amount) + + // Check that the staking contract received the tokens + expect(await grt.balanceOf(staking.address)).eq(amount) + // Check the token lock wallet balance + expect(await grt.balanceOf(tokenLock.address)).eq(transferredAmount.sub(amount)) + }) + it('creates a wallet that has zero releasable amount until the end of the vesting period', async function () { + // ABI-encoded callhook data + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + const walletDataType = 'tuple(address,address,address,uint256,uint256,uint256)' + const data = defaultAbiCoder.encode( + [walletDataType], + [ + [ + l1TokenLock.address, + initArgs.owner, + initArgs.beneficiary, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + + const expectedL2Address = await tokenLockManager['getDeploymentAddress(bytes32,address,address)']( + keccak256(data), + tokenLockImplementation.address, + tokenLockManager.address, + ) + + // Assume part of the managed amount were used in L1, so we don't get all of it + const transferredAmount = initArgs.managedAmount.sub(toGRT('100000')) + + // Call onTokenTransfer from the gateway: + await tokenLockManager + .connect(gateway.signer) + .onTokenTransfer(l1TransferToolMock.address, transferredAmount, data) + + // Check that the token lock wallet was created with the correct parameters + const tokenLock = (await ethers.getContractAt( + 'L2GraphTokenLockWallet', + expectedL2Address, + deployer.signer, + )) as L2GraphTokenLockWallet + + // Check that the releasable amount is zero + expect(await tokenLock.releasableAmount()).eq(0) + // After a few blocks, check that the releasable amount is still zero + await advanceTimeAndBlock(3600 * 24 * 90) + expect(await tokenLock.releasableAmount()).eq(0) + // And available amount should also be zero + expect(await tokenLock.availableAmount()).eq(0) + + // Advance time to the end of the vesting period + await advanceTimeAndBlock(3600 * 24 * 181) + // Check that the releasable amount is the full amount transferred + expect(await tokenLock.releasableAmount()).eq(transferredAmount) + // And available amount should also be the full managed amount + expect(await tokenLock.availableAmount()).eq(initArgs.managedAmount) + }) + }) +}) diff --git a/packages/token-distribution/test/l2TokenLockTransferTool.test.ts b/packages/token-distribution/test/l2TokenLockTransferTool.test.ts new file mode 100644 index 000000000..8f762cc63 --- /dev/null +++ b/packages/token-distribution/test/l2TokenLockTransferTool.test.ts @@ -0,0 +1,263 @@ +import { deployments, ethers, upgrades } from 'hardhat' +import { constants } from 'ethers' +import { expect } from 'chai' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { L2GraphTokenLockManager } from '../build/typechain/contracts/L2GraphTokenLockManager' +import { L2GraphTokenLockTransferTool } from '../build/typechain/contracts/L2GraphTokenLockTransferTool' +import { L2GraphTokenLockTransferTool__factory } from '../build/typechain/contracts/factories/L2GraphTokenLockTransferTool__factory' +import { L2GraphTokenLockWallet } from '../build/typechain/contracts/L2GraphTokenLockWallet' +import { L2TokenGatewayMock } from '../build/typechain/contracts/L2TokenGatewayMock' + +import { Account, getAccounts, getContract, toBN, toGRT } from './network' +import { defaultAbiCoder, keccak256 } from 'ethers/lib/utils' +import { defaultInitArgs, TokenLockParameters } from './config' +import { DeployOptions } from 'hardhat-deploy/types' + +const { AddressZero } = constants + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + const [deployer, , l1TransferToolMock, l1GRTMock] = await getAccounts() + + // Start from a fresh snapshot + await deployments.fixture([]) + + // Deploy token + await deploy('GraphTokenMock', { + from: deployer.address, + args: [toGRT('1000000000'), deployer.address], + }) + const grt = await getContract('GraphTokenMock') + + // Deploy token lock masterCopy + await deploy('L2GraphTokenLockWallet', { + from: deployer.address, + }) + const tokenLockWallet = await getContract('L2GraphTokenLockWallet') + + // Deploy the gateway mock + await deploy('L2TokenGatewayMock', { + from: deployer.address, + args: [l1GRTMock.address, grt.address], + }) + const gateway = await getContract('L2TokenGatewayMock') + + // Deploy token lock manager + await deploy('L2GraphTokenLockManager', { + from: deployer.address, + args: [grt.address, tokenLockWallet.address, gateway.address, l1TransferToolMock.address], + }) + const tokenLockManager = await getContract('L2GraphTokenLockManager') + + // Deploy the L2GraphTokenLockTransferTool using a proxy + + // Deploy transfer tool using a proxy + const transferToolFactory = await ethers.getContractFactory('L2GraphTokenLockTransferTool') + const tokenLockTransferTool = (await upgrades.deployProxy(transferToolFactory, [], { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [grt.address, gateway.address, l1GRTMock.address], + })) as L2GraphTokenLockTransferTool + + // Fund the manager contract + await grt.connect(deployer.signer).transfer(tokenLockManager.address, toGRT('100000000')) + + return { + grt: grt as GraphTokenMock, + gateway: gateway as L2TokenGatewayMock, + tokenLockTransferTool: tokenLockTransferTool, + tokenLockImplementation: tokenLockWallet as L2GraphTokenLockWallet, + tokenLockManager: tokenLockManager as L2GraphTokenLockManager, + } +}) + +async function authProtocolFunctions(tokenLockManager: L2GraphTokenLockManager, tokenLockTransferToolAddress: string) { + await tokenLockManager.setAuthFunctionCall('withdrawToL1Locked(uint256)', tokenLockTransferToolAddress) +} + +describe('L2GraphTokenLockTransferTool', () => { + let deployer: Account + let beneficiary: Account + let l1TransferToolMock: Account + let l1GRTMock: Account + let l1TokenLock: Account + + let grt: GraphTokenMock + let tokenLock: L2GraphTokenLockWallet + let tokenLockImplementation: L2GraphTokenLockWallet + let tokenLockManager: L2GraphTokenLockManager + let tokenLockTransferTool: L2GraphTokenLockTransferTool + let gateway: L2TokenGatewayMock + let lockAsTransferTool: L2GraphTokenLockTransferTool + + let initArgs: TokenLockParameters + + const initWithArgs = async (args: TokenLockParameters): Promise => { + const tx = await tokenLockManager.createTokenLockWallet( + args.owner, + args.beneficiary, + args.managedAmount, + args.startTime, + args.endTime, + args.periods, + args.releaseStartTime, + args.vestingCliffTime, + args.revocable, + ) + const receipt = await tx.wait() + const contractAddress = receipt.events[0].args['proxy'] + return ethers.getContractAt('L2GraphTokenLockWallet', contractAddress) as Promise + } + + const initFromL1 = async (): Promise => { + // First we mock creating a token lock wallet through the gateway + // ABI-encoded callhook data + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + const walletDataType = 'tuple(address,address,address,uint256,uint256,uint256)' + const data = defaultAbiCoder.encode( + [walletDataType], + [ + [ + l1TokenLock.address, + initArgs.owner, + initArgs.beneficiary, + initArgs.managedAmount, + initArgs.startTime, + initArgs.endTime, + ], + ], + ) + + // Mock the gateway call + const tx = gateway.finalizeInboundTransfer( + l1GRTMock.address, + l1TransferToolMock.address, + tokenLockManager.address, + toGRT('35000000'), + data, + ) + + await expect(tx).emit(tokenLockManager, 'TokenLockCreatedFromL1') + + const expectedL2Address = await tokenLockManager['getDeploymentAddress(bytes32,address,address)']( + keccak256(data), + tokenLockImplementation.address, + tokenLockManager.address, + ) + + return ethers.getContractAt('L2GraphTokenLockWallet', expectedL2Address) as Promise + } + + before(async function () { + [deployer, beneficiary, l1TransferToolMock, l1GRTMock, l1TokenLock] = await getAccounts() + }) + + beforeEach(async () => { + ({ grt, gateway, tokenLockTransferTool, tokenLockImplementation, tokenLockManager } = await setupTest()) + + // Setup authorized functions in Manager + await authProtocolFunctions(tokenLockManager, tokenLockTransferTool.address) + + // Add the transfer tool contract as token destination + await tokenLockManager.addTokenDestination(tokenLockTransferTool.address) + }) + + describe('Upgrades', function () { + it('should be upgradeable', async function () { + const transferToolFactory = await ethers.getContractFactory('L2GraphTokenLockTransferTool') + tokenLockTransferTool = (await upgrades.upgradeProxy(tokenLockTransferTool.address, transferToolFactory, { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [beneficiary.address, gateway.address, l1GRTMock.address], + })) as L2GraphTokenLockTransferTool + expect(await tokenLockTransferTool.graphToken()).to.eq(beneficiary.address) + tokenLockTransferTool = (await upgrades.upgradeProxy(tokenLockTransferTool.address, transferToolFactory, { + kind: 'transparent', + unsafeAllow: ['state-variable-immutable', 'constructor'], + constructorArgs: [grt.address, gateway.address, l1GRTMock.address], + })) as L2GraphTokenLockTransferTool + expect(await tokenLockTransferTool.graphToken()).to.eq(grt.address) + }) + }) + describe('withdrawToL1Locked', function () { + it('allows a token lock wallet to send GRT to L1 through the gateway', async function () { + tokenLock = await initFromL1() + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + + lockAsTransferTool = L2GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + + const amountToSend = toGRT('1000000') + const tx = await lockAsTransferTool.connect(beneficiary.signer).withdrawToL1Locked(amountToSend) + + await expect(tx).emit(gateway, 'WithdrawalInitiated').withArgs( + l1GRTMock.address, + tokenLockTransferTool.address, + l1TokenLock.address, + toBN('0'), // sequence number + amountToSend, + ) + await expect(tx) + .emit(tokenLockTransferTool, 'LockedFundsSentToL1') + .withArgs(l1TokenLock.address, tokenLock.address, tokenLockManager.address, amountToSend) + }) + it('rejects calls from a lock that was not transferred from L1', async function () { + tokenLock = await initWithArgs(defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000'))) + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + + lockAsTransferTool = L2GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + + const amountToSend = toGRT('1000000') + const tx = lockAsTransferTool.connect(beneficiary.signer).withdrawToL1Locked(amountToSend) + + await expect(tx).to.be.revertedWith('NOT_L1_WALLET') + }) + it('rejects calls from an address that is not a lock (has no manager)', async function () { + const tx = tokenLockTransferTool.connect(beneficiary.signer).withdrawToL1Locked(toGRT('1000000')) + await expect(tx).to.be.reverted // Function call to a non-contract account + }) + it('rejects calls from an address that has a manager() function that returns zero', async function () { + // Use WalletMock to simulate an invalid wallet with no manager + // WalletMock constructor args are: target, token, manager, isInitialized, isAccepted + await deployments.deploy('WalletMock', { + from: deployer.address, + args: [tokenLockTransferTool.address, grt.address, AddressZero, true, true], + }) + const invalidWallet = await getContract('WalletMock') + const walletAsTransferTool = L2GraphTokenLockTransferTool__factory.connect(invalidWallet.address, deployer.signer) + + const tx = walletAsTransferTool.connect(beneficiary.signer).withdrawToL1Locked(toGRT('1000000')) + await expect(tx).to.be.revertedWith('INVALID_SENDER') + }) + it('rejects calls from a lock that has insufficient GRT balance', async function () { + tokenLock = await initFromL1() + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + + lockAsTransferTool = L2GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + + const amountToSend = toGRT('35000001') + const tx = lockAsTransferTool.connect(beneficiary.signer).withdrawToL1Locked(amountToSend) + + await expect(tx).to.be.revertedWith('INSUFFICIENT_BALANCE') + }) + it('rejects calls trying to send a zero amount', async function () { + tokenLock = await initFromL1() + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + + lockAsTransferTool = L2GraphTokenLockTransferTool__factory.connect(tokenLock.address, deployer.signer) + + const amountToSend = toGRT('0') + const tx = lockAsTransferTool.connect(beneficiary.signer).withdrawToL1Locked(amountToSend) + + await expect(tx).to.be.revertedWith('ZERO_AMOUNT') + }) + }) +}) diff --git a/packages/token-distribution/test/network.ts b/packages/token-distribution/test/network.ts new file mode 100644 index 000000000..2f92cbc19 --- /dev/null +++ b/packages/token-distribution/test/network.ts @@ -0,0 +1,95 @@ +import { BigNumber, Contract, providers, Signer, utils } from 'ethers' +import { deployments, ethers, network, waffle } from 'hardhat' + +// Plugins + +import '@nomiclabs/hardhat-ethers' +import '@nomiclabs/hardhat-waffle' +import 'hardhat-deploy' + +const { hexlify, parseUnits, formatUnits, randomBytes } = utils + +// Utils + +export const toBN = (value: string | number): BigNumber => BigNumber.from(value) +export const toGRT = (value: string): BigNumber => parseUnits(value, '18') +export const formatGRT = (value: BigNumber): string => formatUnits(value, '18') +export const randomHexBytes = (n = 32): string => hexlify(randomBytes(n)) + +// Contracts + +export const getContract = async (contractName: string): Promise => { + const deployment = await deployments.get(contractName) + return ethers.getContractAt(contractName, deployment.address) +} + +// Network + +export interface Account { + readonly signer: Signer + readonly address: string +} + +export const provider = (): providers.JsonRpcProvider => waffle.provider + +export const getAccounts = async (): Promise => { + const accounts: Account[] = [] + const signers: Signer[] = await ethers.getSigners() + for (const signer of signers) { + accounts.push({ signer, address: await signer.getAddress() }) + } + return accounts +} + +export const getChainID = (): Promise => { + // HACK: this fixes ganache returning always 1 when a contract calls the chainid() opcode + if (network.name == 'ganache') { + return Promise.resolve(1) + } + return provider() + .getNetwork() + .then(r => r.chainId) +} + +export const latestBlockNum = (): Promise => provider().getBlockNumber().then(toBN) +export const latestBlock = async (): Promise => provider().getBlock(await provider().getBlockNumber()) +export const latestBlockTime = async (): Promise => latestBlock().then(block => block.timestamp) + +export const advanceBlock = (): Promise => { + return provider().send('evm_mine', []) as Promise +} + +export const advanceBlockTo = async (blockNumber: string | number | BigNumber): Promise => { + const target = typeof blockNumber === 'number' || typeof blockNumber === 'string' ? toBN(blockNumber) : blockNumber + const currentBlock = await latestBlockNum() + const start = Date.now() + let notified: boolean + if (target.lt(currentBlock)) throw Error(`Target block #(${target.toString()}) is lower than current block #(${currentBlock.toString()})`) + while ((await latestBlockNum()).lt(target)) { + if (!notified && Date.now() - start >= 5000) { + notified = true + console.log(`advanceBlockTo: Advancing too ` + 'many blocks is causing this test to be slow.') + } + await advanceBlock() + } +} + +export const advanceBlocks = async (blocks: string | number | BigNumber): Promise => { + const steps = typeof blocks === 'number' || typeof blocks === 'string' ? toBN(blocks) : blocks + const currentBlock = await latestBlockNum() + const toBlock = currentBlock.add(steps) + await advanceBlockTo(toBlock) +} + +export const advanceTime = async (time: number): Promise => { + return provider().send('evm_increaseTime', [time]) as Promise +} + +export const advanceTimeAndBlock = async (time: number): Promise => { + await advanceTime(time) + await advanceBlock() + return latestBlockNum() +} + +export const evmSnapshot = async (): Promise => provider().send('evm_snapshot', []) as Promise +export const evmRevert = async (id: number): Promise => provider().send('evm_revert', [id]) as Promise diff --git a/packages/token-distribution/test/tokenLock.test.ts b/packages/token-distribution/test/tokenLock.test.ts new file mode 100644 index 000000000..5c8be9a75 --- /dev/null +++ b/packages/token-distribution/test/tokenLock.test.ts @@ -0,0 +1,771 @@ +import 'hardhat-deploy' +import { BigNumber, constants } from 'ethers' +import { deployments } from 'hardhat' +import { expect } from 'chai' + +import { GraphTokenLockSimple } from '../build/typechain/contracts/GraphTokenLockSimple' +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' + +import { Account, advanceTimeAndBlock, getAccounts, getContract, toBN, toGRT } from './network' +import { createScheduleScenarios, defaultInitArgs, Revocability, TokenLockParameters } from './config' +import { DeployOptions } from 'hardhat-deploy/types' + +const { AddressZero } = constants + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + const [deployer] = await getAccounts() + + // Start from a fresh snapshot + await deployments.fixture([]) + + // Deploy token + await deploy('GraphTokenMock', { + from: deployer.address, + args: [toGRT('1000000000'), deployer.address], + }) + const grt = await getContract('GraphTokenMock') + + // Deploy token lock + await deploy('GraphTokenLockSimple', { + from: deployer.address, + args: [], + }) + const tokenLock = await getContract('GraphTokenLockSimple') + + return { + grt: grt as GraphTokenMock, + tokenLock: tokenLock as GraphTokenLockSimple, + } +}) + +// -- Time utils -- + +const advancePeriods = async (tokenLock: GraphTokenLockSimple, n = 1) => { + const periodDuration = await tokenLock.periodDuration() + return advanceTimeAndBlock(periodDuration.mul(n).toNumber()) // advance N period +} + +const moveToTime = async (tokenLock: GraphTokenLockSimple, target: BigNumber, buffer: number) => { + const ts = await tokenLock.currentTime() + const delta = target.sub(ts).add(buffer) + return advanceTimeAndBlock(delta.toNumber()) +} + +const advanceToStart = async (tokenLock: GraphTokenLockSimple) => moveToTime(tokenLock, await tokenLock.startTime(), 60) +const advanceToEnd = async (tokenLock: GraphTokenLockSimple) => moveToTime(tokenLock, await tokenLock.endTime(), 60) +const advanceToAboutStart = async (tokenLock: GraphTokenLockSimple) => + moveToTime(tokenLock, await tokenLock.startTime(), -60) +const advanceToReleasable = async (tokenLock: GraphTokenLockSimple) => { + const values = await Promise.all([ + tokenLock.vestingCliffTime(), + tokenLock.releaseStartTime(), + tokenLock.startTime(), + ]).then(values => values.map(e => e.toNumber())) + const time = Math.max(...values) + await moveToTime(tokenLock, BigNumber.from(time), 60) +} + +const forEachPeriod = async (tokenLock: GraphTokenLockSimple, fn) => { + const periods = (await tokenLock.periods()).toNumber() + for (let currentPeriod = 1; currentPeriod <= periods + 1; currentPeriod++) { + const currentPeriod = await tokenLock.currentPeriod() + // console.log('\t ✓ period ->', currentPeriod.toString()) + await fn(currentPeriod.sub(1), currentPeriod) + await advancePeriods(tokenLock, 1) + } +} + +const shouldMatchSchedule = async (tokenLock: GraphTokenLockSimple, fnName: string, initArgs: TokenLockParameters) => { + await forEachPeriod(tokenLock, async function (passedPeriods: BigNumber) { + const amount = (await tokenLock.functions[fnName]())[0] + const amountPerPeriod = await tokenLock.amountPerPeriod() + const managedAmount = await tokenLock.managedAmount() + + // console.log(`\t - amount: ${formatGRT(amount)}/${formatGRT(managedAmount)}`) + + // After last period we expect to have all managed tokens available + const expectedAmount = passedPeriods.lt(initArgs.periods) ? passedPeriods.mul(amountPerPeriod) : managedAmount + expect(amount).eq(expectedAmount) + }) +} + +// -- Tests -- + +describe('GraphTokenLockSimple', () => { + let deployer: Account + let beneficiary1: Account + let beneficiary2: Account + + let grt: GraphTokenMock + let tokenLock: GraphTokenLockSimple + + let initArgs: TokenLockParameters + + const initWithArgs = (args: TokenLockParameters) => { + return tokenLock + .connect(deployer.signer) + .initialize( + args.owner, + args.beneficiary, + args.token, + args.managedAmount, + args.startTime, + args.endTime, + args.periods, + args.releaseStartTime, + args.vestingCliffTime, + args.revocable, + ) + } + + const fundContract = async (contract: GraphTokenLockSimple) => { + const managedAmount = await contract.managedAmount() + await grt.connect(deployer.signer).transfer(contract.address, managedAmount) + } + + before(async function () { + [deployer, beneficiary1, beneficiary2] = await getAccounts() + }) + + describe('Init', function () { + it('Reject initialize with non-set revocability option', async function () { + ({ grt, tokenLock } = await setupTest()) + + const args = defaultInitArgs(deployer, beneficiary1, grt, toGRT('1000')) + const tx = tokenLock + .connect(deployer.signer) + .initialize( + args.owner, + args.beneficiary, + args.token, + args.managedAmount, + args.startTime, + args.endTime, + args.periods, + 0, + 0, + Revocability.NotSet, + ) + await expect(tx).revertedWith('Must set a revocability option') + }) + }) + + createScheduleScenarios().forEach(function (schedule) { + describe('> Test scenario', function () { + beforeEach(async function () { + ({ grt, tokenLock } = await setupTest()) + + const staticArgs = { + owner: deployer.address, + beneficiary: beneficiary1.address, + token: grt.address, + managedAmount: toGRT('35000000'), + } + initArgs = { ...staticArgs, ...schedule } + await initWithArgs(initArgs) + + // Move time to just before the contract starts + await advanceToAboutStart(tokenLock) + }) + + describe('Init', function () { + it('reject re-initialization', async function () { + const tx = initWithArgs(initArgs) + await expect(tx).revertedWith('Already initialized') + }) + + it('should be each parameter initialized properly', async function () { + console.log('\t>> Scenario ', JSON.stringify(schedule)) + + expect(await tokenLock.beneficiary()).eq(initArgs.beneficiary) + expect(await tokenLock.managedAmount()).eq(initArgs.managedAmount) + expect(await tokenLock.startTime()).eq(initArgs.startTime) + expect(await tokenLock.endTime()).eq(initArgs.endTime) + expect(await tokenLock.periods()).eq(initArgs.periods) + expect(await tokenLock.token()).eq(initArgs.token) + expect(await tokenLock.releaseStartTime()).eq(initArgs.releaseStartTime) + expect(await tokenLock.vestingCliffTime()).eq(initArgs.vestingCliffTime) + expect(await tokenLock.revocable()).eq(initArgs.revocable) + }) + }) + + describe('Balance', function () { + describe('currentBalance()', function () { + it('should match to deposited balance', async function () { + // Before + expect(await tokenLock.currentBalance()).eq(0) + + // Transfer + const totalAmount = toGRT('100') + await grt.connect(deployer.signer).transfer(tokenLock.address, totalAmount) + + // After + expect(await tokenLock.currentBalance()).eq(totalAmount) + }) + }) + }) + + describe('Time & periods', function () { + // describe('currentTime()', function () { + // it('should return current block time', async function () { + // expect(await tokenLock.currentTime()).eq(await latestBlockTime()) + // }) + // }) + + describe('duration()', function () { + it('should match init parameters', async function () { + const duration = initArgs.endTime - initArgs.startTime + expect(await tokenLock.duration()).eq(toBN(duration)) + }) + }) + + describe('sinceStartTime()', function () { + it('should be zero if currentTime < startTime', async function () { + const now = +new Date() / 1000 + if (now < initArgs.startTime) { + expect(await tokenLock.sinceStartTime()).eq(0) + } + }) + + it('should be right amount of time elapsed', async function () { + await advanceTimeAndBlock(initArgs.startTime + 60) + + const elapsedTime = (await tokenLock.currentTime()).sub(initArgs.startTime) + expect(await tokenLock.sinceStartTime()).eq(elapsedTime) + }) + }) + + describe('amountPerPeriod()', function () { + it('should match init parameters', async function () { + const amountPerPeriod = initArgs.managedAmount.div(initArgs.periods) + expect(await tokenLock.amountPerPeriod()).eq(amountPerPeriod) + }) + }) + + describe('periodDuration()', function () { + it('should match init parameters', async function () { + const periodDuration = toBN(initArgs.endTime - initArgs.startTime).div(initArgs.periods) + expect(await tokenLock.periodDuration()).eq(periodDuration) + }) + }) + + describe('currentPeriod()', function () { + it('should be one (1) before start time', async function () { + expect(await tokenLock.currentPeriod()).eq(1) + }) + + it('should return correct amount for each period', async function () { + await advanceToStart(tokenLock) + + for (let currentPeriod = 1; currentPeriod <= initArgs.periods; currentPeriod++) { + expect(await tokenLock.currentPeriod()).eq(currentPeriod) + // console.log('\t ✓ period ->', currentPeriod) + await advancePeriods(tokenLock, 1) + } + }) + }) + + describe('passedPeriods()', function () { + it('should return correct amount for each period', async function () { + await advanceToStart(tokenLock) + + for (let currentPeriod = 1; currentPeriod <= initArgs.periods; currentPeriod++) { + expect(await tokenLock.passedPeriods()).eq(currentPeriod - 1) + // console.log('\t ✓ period ->', currentPeriod) + await advancePeriods(tokenLock, 1) + } + }) + }) + }) + + describe('Locking & release', function () { + describe('availableAmount()', function () { + it('should return zero before start time', async function () { + expect(await tokenLock.availableAmount()).eq(0) + }) + + it('should return correct amount for each period', async function () { + await advanceToStart(tokenLock) + await shouldMatchSchedule(tokenLock, 'availableAmount', initArgs) + }) + + it('should return full managed amount after end time', async function () { + await advanceToEnd(tokenLock) + + const managedAmount = await tokenLock.managedAmount() + expect(await tokenLock.availableAmount()).eq(managedAmount) + }) + }) + + describe('vestedAmount()', function () { + it('should be fully vested if non-revocable', async function () { + const revocable: Revocability = await tokenLock.revocable() + const vestedAmount = await tokenLock.vestedAmount() + if (revocable === Revocability.Disabled) { + expect(vestedAmount).eq(await tokenLock.managedAmount()) + } + }) + + it('should match the vesting schedule if revocable', async function () { + if (initArgs.revocable === Revocability.Disabled) return + + const cliffTime = await tokenLock.vestingCliffTime() + + await forEachPeriod(tokenLock, async function (passedPeriods: BigNumber) { + const amount = (await tokenLock.functions['vestedAmount']())[0] + const amountPerPeriod = await tokenLock.amountPerPeriod() + const managedAmount = await tokenLock.managedAmount() + const currentTime = await tokenLock.currentTime() + + // console.log(`\t - amount: ${formatGRT(amount)}/${formatGRT(managedAmount)}`) + + let expectedAmount = managedAmount + // Before cliff no vested tokens + if (cliffTime.gt(0) && currentTime.lt(cliffTime)) { + expectedAmount = BigNumber.from(0) + } else { + // After last period we expect to have all managed tokens available + if (passedPeriods.lt(initArgs.periods)) { + expectedAmount = passedPeriods.mul(amountPerPeriod) + } + } + expect(amount).eq(expectedAmount) + }) + }) + }) + + describe('releasableAmount()', function () { + it('should always return zero if there is no balance in the contract', async function () { + await forEachPeriod(tokenLock, async function () { + const releasableAmount = await tokenLock.releasableAmount() + expect(releasableAmount).eq(0) + }) + }) + + context('> when funded', function () { + beforeEach(async function () { + await fundContract(tokenLock) + }) + + it('should match the release schedule', async function () { + await advanceToReleasable(tokenLock) + await shouldMatchSchedule(tokenLock, 'releasableAmount', initArgs) + }) + + it('should subtract already released amount', async function () { + await advanceToReleasable(tokenLock) + + // After one period release + await advancePeriods(tokenLock, 1) + const releasableAmountPeriod1 = await tokenLock.releasableAmount() + await tokenLock.connect(beneficiary1.signer).release() + + // Next periods test that we are not counting released amount on previous period + await advancePeriods(tokenLock, 2) + const availableAmount = await tokenLock.availableAmount() + const releasableAmountPeriod2 = await tokenLock.releasableAmount() + expect(releasableAmountPeriod2).eq(availableAmount.sub(releasableAmountPeriod1)) + }) + }) + }) + + describe('totalOutstandingAmount()', function () { + it('should be the total managed amount when have not released yet', async function () { + const managedAmount = await tokenLock.managedAmount() + const totalOutstandingAmount = await tokenLock.totalOutstandingAmount() + expect(totalOutstandingAmount).eq(managedAmount) + }) + + context('when funded', function () { + beforeEach(async function () { + await fundContract(tokenLock) + }) + + it('should be the total managed when have not started', async function () { + const managedAmount = await tokenLock.managedAmount() + const totalOutstandingAmount = await tokenLock.totalOutstandingAmount() + expect(totalOutstandingAmount).eq(managedAmount) + }) + + it('should be the total managed less the already released amount', async function () { + // Setup + await advanceToReleasable(tokenLock) + await advancePeriods(tokenLock, 1) + + // Release + const amountToRelease = await tokenLock.releasableAmount() + await tokenLock.connect(beneficiary1.signer).release() + + const managedAmount = await tokenLock.managedAmount() + const totalOutstandingAmount = await tokenLock.totalOutstandingAmount() + expect(totalOutstandingAmount).eq(managedAmount.sub(amountToRelease)) + }) + + it('should be zero when all funds have been released', async function () { + // Setup + await advanceToEnd(tokenLock) + + // Release + await tokenLock.connect(beneficiary1.signer).release() + + // Test + const totalOutstandingAmount = await tokenLock.totalOutstandingAmount() + expect(totalOutstandingAmount).eq(0) + }) + }) + }) + + describe('surplusAmount()', function () { + it('should be zero when balance under outstanding amount', async function () { + // Setup + await fundContract(tokenLock) + await advanceToStart(tokenLock) + + // Test + const surplusAmount = await tokenLock.surplusAmount() + expect(surplusAmount).eq(0) + }) + + it('should return any balance over outstanding amount', async function () { + // Setup + await fundContract(tokenLock) + await advanceToReleasable(tokenLock) + await advancePeriods(tokenLock, 1) + await tokenLock.connect(beneficiary1.signer).release() + + // Send extra amount + await grt.connect(deployer.signer).transfer(tokenLock.address, toGRT('1000')) + + // Test + const surplusAmount = await tokenLock.surplusAmount() + expect(surplusAmount).eq(toGRT('1000')) + }) + }) + }) + + describe('Beneficiary admin', function () { + describe('changeBeneficiary()', function () { + it('should change beneficiary', async function () { + const tx = tokenLock.connect(beneficiary1.signer).changeBeneficiary(beneficiary2.address) + await expect(tx).emit(tokenLock, 'BeneficiaryChanged').withArgs(beneficiary2.address) + + const afterBeneficiary = await tokenLock.beneficiary() + expect(afterBeneficiary).eq(beneficiary2.address) + }) + + it('reject if beneficiary is zero', async function () { + const tx = tokenLock.connect(beneficiary1.signer).changeBeneficiary(AddressZero) + await expect(tx).revertedWith('Empty beneficiary') + }) + + it('reject if not authorized', async function () { + const tx = tokenLock.connect(deployer.signer).changeBeneficiary(beneficiary2.address) + await expect(tx).revertedWith('!auth') + }) + }) + }) + + describe('Recovery', function () { + beforeEach(async function () { + await fundContract(tokenLock) + }) + + it('should cancel lock and return funds to owner', async function () { + const beforeBalance = await grt.balanceOf(deployer.address) + const contractBalance = await grt.balanceOf(tokenLock.address) + const tx = tokenLock.connect(deployer.signer).cancelLock() + await expect(tx).emit(tokenLock, 'LockCanceled') + + const afterBalance = await grt.balanceOf(deployer.address) + const diff = afterBalance.sub(beforeBalance) + expect(diff).eq(contractBalance) + }) + + it('reject cancel lock from non-owner', async function () { + const tx = tokenLock.connect(beneficiary1.signer).cancelLock() + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + + it('should accept lock', async function () { + expect(await tokenLock.isAccepted()).eq(false) + const tx = tokenLock.connect(beneficiary1.signer).acceptLock() + await expect(tx).emit(tokenLock, 'LockAccepted') + expect(await tokenLock.isAccepted()).eq(true) + }) + + it('reject accept lock from non-beneficiary', async function () { + expect(await tokenLock.isAccepted()).eq(false) + const tx = tokenLock.connect(deployer.signer).acceptLock() + await expect(tx).revertedWith('!auth') + }) + + it('reject cancel after contract accepted', async function () { + await tokenLock.connect(beneficiary1.signer).acceptLock() + + const tx = tokenLock.connect(deployer.signer).cancelLock() + await expect(tx).revertedWith('Cannot cancel accepted contract') + }) + }) + + describe('Value transfer', function () { + async function getState(tokenLock: GraphTokenLockSimple) { + const beneficiaryAddress = await tokenLock.beneficiary() + const ownerAddress = await tokenLock.owner() + return { + beneficiaryBalance: await grt.balanceOf(beneficiaryAddress), + contractBalance: await grt.balanceOf(tokenLock.address), + ownerBalance: await grt.balanceOf(ownerAddress), + } + } + + describe('release()', function () { + it('should release the scheduled amount', async function () { + // Setup + await fundContract(tokenLock) + await advanceToReleasable(tokenLock) + await advancePeriods(tokenLock, 1) + + // Before state + const before = await getState(tokenLock) + + // Release + const amountToRelease = await tokenLock.releasableAmount() + const tx = tokenLock.connect(beneficiary1.signer).release() + await expect(tx).emit(tokenLock, 'TokensReleased').withArgs(beneficiary1.address, amountToRelease) + + // After state + const after = await getState(tokenLock) + expect(after.beneficiaryBalance).eq(before.beneficiaryBalance.add(amountToRelease)) + expect(after.contractBalance).eq(before.contractBalance.sub(amountToRelease)) + expect(await tokenLock.releasableAmount()).eq(0) + }) + + it('should release only vested amount after being revoked', async function () { + if (initArgs.revocable === Revocability.Disabled) return + + // Setup + await fundContract(tokenLock) + await advanceToStart(tokenLock) + + // Move to cliff if any + if (initArgs.vestingCliffTime) { + await moveToTime(tokenLock, await tokenLock.vestingCliffTime(), 60) + } + + // Vest some amount + await advancePeriods(tokenLock, 2) // fwd two periods + + // Owner revokes the contract + await tokenLock.connect(deployer.signer).revoke() + const vestedAmount = await tokenLock.vestedAmount() + + // Some more periods passed + await advancePeriods(tokenLock, 2) // fwd two periods + + // Release + const tx = tokenLock.connect(beneficiary1.signer).release() + await expect(tx).emit(tokenLock, 'TokensReleased').withArgs(beneficiary1.address, vestedAmount) + }) + + it('reject release vested amount before cliff', async function () { + if (initArgs.revocable === Revocability.Disabled) return + if (!initArgs.vestingCliffTime) return + + // Setup + await fundContract(tokenLock) + await advanceToStart(tokenLock) + await advancePeriods(tokenLock, 2) // fwd two periods + + // Release before cliff + const tx1 = tokenLock.connect(beneficiary1.signer).release() + await expect(tx1).revertedWith('No available releasable amount') + + // Release after cliff + await moveToTime(tokenLock, await tokenLock.vestingCliffTime(), 60) + await tokenLock.connect(beneficiary1.signer).release() + }) + + it('reject release if no funds available', async function () { + // Setup + await fundContract(tokenLock) + + // Release + const tx = tokenLock.connect(beneficiary1.signer).release() + await expect(tx).revertedWith('No available releasable amount') + }) + + it('reject release if not the beneficiary', async function () { + const tx = tokenLock.connect(beneficiary2.signer).release() + await expect(tx).revertedWith('!auth') + }) + }) + + describe('withdrawSurplus()', function () { + it('should withdraw surplus balance that is over managed amount', async function () { + // Setup + const managedAmount = await tokenLock.managedAmount() + const amountToWithdraw = toGRT('100') + const totalAmount = managedAmount.add(amountToWithdraw) + await grt.connect(deployer.signer).transfer(tokenLock.address, totalAmount) + + // Revert if trying to withdraw more than managed amount + const tx1 = tokenLock.connect(beneficiary1.signer).withdrawSurplus(amountToWithdraw.add(1)) + await expect(tx1).revertedWith('Amount requested > surplus available') + + // Before state + const before = await getState(tokenLock) + + // Should withdraw + const tx2 = tokenLock.connect(beneficiary1.signer).withdrawSurplus(amountToWithdraw) + await expect(tx2).emit(tokenLock, 'TokensWithdrawn').withArgs(beneficiary1.address, amountToWithdraw) + + // After state + const after = await getState(tokenLock) + expect(after.beneficiaryBalance).eq(before.beneficiaryBalance.add(amountToWithdraw)) + expect(after.contractBalance).eq(before.contractBalance.sub(amountToWithdraw)) + }) + + it('should withdraw surplus balance that is over managed amount (less than total available)', async function () { + // Setup + const managedAmount = await tokenLock.managedAmount() + const surplusAmount = toGRT('100') + const totalAmount = managedAmount.add(surplusAmount) + await grt.connect(deployer.signer).transfer(tokenLock.address, totalAmount) + + // Should withdraw + const tx2 = tokenLock.connect(beneficiary1.signer).withdrawSurplus(surplusAmount.sub(1)) + await expect(tx2).emit(tokenLock, 'TokensWithdrawn').withArgs(beneficiary1.address, surplusAmount.sub(1)) + }) + + it('should withdraw surplus balance even after the contract was released->revoked', async function () { + if (initArgs.revocable === Revocability.Enabled) { + // Setup + const managedAmount = await tokenLock.managedAmount() + const surplusAmount = toGRT('100') + const totalAmount = managedAmount.add(surplusAmount) + await grt.connect(deployer.signer).transfer(tokenLock.address, totalAmount) + + // Vest some amount + await advanceToReleasable(tokenLock) + await advancePeriods(tokenLock, 2) // fwd two periods + + // Release / Revoke + await tokenLock.connect(beneficiary1.signer).release() + await tokenLock.connect(deployer.signer).revoke() + + // Should withdraw + const tx2 = tokenLock.connect(beneficiary1.signer).withdrawSurplus(surplusAmount) + await expect(tx2).emit(tokenLock, 'TokensWithdrawn').withArgs(beneficiary1.address, surplusAmount) + + // Contract must have no balance after all actions + const balance = await grt.balanceOf(tokenLock.address) + expect(balance).eq(0) + } + }) + + it('should withdraw surplus balance even after the contract was revoked->released', async function () { + if (initArgs.revocable === Revocability.Enabled) { + // Setup + const managedAmount = await tokenLock.managedAmount() + const surplusAmount = toGRT('100') + const totalAmount = managedAmount.add(surplusAmount) + await grt.connect(deployer.signer).transfer(tokenLock.address, totalAmount) + + // Vest some amount + await advanceToReleasable(tokenLock) + await advancePeriods(tokenLock, 2) // fwd two periods + + // Release / Revoke + await tokenLock.connect(deployer.signer).revoke() + await tokenLock.connect(beneficiary1.signer).release() + + // Should withdraw + const tx2 = tokenLock.connect(beneficiary1.signer).withdrawSurplus(surplusAmount) + await expect(tx2).emit(tokenLock, 'TokensWithdrawn').withArgs(beneficiary1.address, surplusAmount) + + // Contract must have no balance after all actions + const balance = await grt.balanceOf(tokenLock.address) + expect(balance).eq(0) + } + }) + + it('reject withdraw if not the beneficiary', async function () { + await grt.connect(deployer.signer).transfer(tokenLock.address, toGRT('100')) + + const tx = tokenLock.connect(beneficiary2.signer).withdrawSurplus(toGRT('100')) + await expect(tx).revertedWith('!auth') + }) + + it('reject withdraw zero tokens', async function () { + const tx = tokenLock.connect(beneficiary1.signer).withdrawSurplus(toGRT('0')) + await expect(tx).revertedWith('Amount cannot be zero') + }) + + it('reject withdraw more than available funds', async function () { + const tx = tokenLock.connect(beneficiary1.signer).withdrawSurplus(toGRT('100')) + await expect(tx).revertedWith('Amount requested > surplus available') + }) + }) + + describe('revoke()', function () { + beforeEach(async function () { + await fundContract(tokenLock) + await advanceToStart(tokenLock) + }) + + it('should revoke and get funds back to owner', async function () { + if (initArgs.revocable === Revocability.Enabled) { + // Before state + const before = await getState(tokenLock) + + // Revoke + const beneficiaryAddress = await tokenLock.beneficiary() + const vestedAmount = await tokenLock.vestedAmount() + const managedAmount = await tokenLock.managedAmount() + const unvestedAmount = managedAmount.sub(vestedAmount) + const tx = tokenLock.connect(deployer.signer).revoke() + await expect(tx).emit(tokenLock, 'TokensRevoked').withArgs(beneficiaryAddress, unvestedAmount) + + // After state + const after = await getState(tokenLock) + expect(after.ownerBalance).eq(before.ownerBalance.add(unvestedAmount)) + } + }) + + it('reject revoke multiple times', async function () { + if (initArgs.revocable === Revocability.Enabled) { + await tokenLock.connect(deployer.signer).revoke() + const tx = tokenLock.connect(deployer.signer).revoke() + await expect(tx).revertedWith('Already revoked') + } + }) + + it('reject revoke if not authorized', async function () { + const tx = tokenLock.connect(beneficiary1.signer).revoke() + await expect(tx).revertedWith('Ownable: caller is not the owner') + }) + + it('reject revoke if not revocable', async function () { + if (initArgs.revocable === Revocability.Disabled) { + const tx = tokenLock.connect(deployer.signer).revoke() + await expect(tx).revertedWith('Contract is non-revocable') + } + }) + + it('reject revoke if no available unvested amount', async function () { + if (initArgs.revocable === Revocability.Enabled) { + // Setup + await advanceToEnd(tokenLock) + + // Try to revoke after all tokens have been vested + const tx = tokenLock.connect(deployer.signer).revoke() + await expect(tx).revertedWith('No available unvested amount') + } + }) + }) + }) + }) + }) +}) diff --git a/packages/token-distribution/test/tokenLockWallet.test.ts b/packages/token-distribution/test/tokenLockWallet.test.ts new file mode 100644 index 000000000..d2b64afdb --- /dev/null +++ b/packages/token-distribution/test/tokenLockWallet.test.ts @@ -0,0 +1,362 @@ +import { BigNumber, constants, Wallet } from 'ethers' +import { deployments, ethers } from 'hardhat' +import { expect } from 'chai' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenLockManager } from '../build/typechain/contracts/GraphTokenLockManager' +import { GraphTokenLockWallet } from '../build/typechain/contracts/GraphTokenLockWallet' +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { StakingMock } from '../build/typechain/contracts/StakingMock' + +import { Staking__factory } from '@graphprotocol/contracts/dist/types/factories/Staking__factory' + +import { Account, advanceBlocks, advanceTimeAndBlock, getAccounts, getContract, randomHexBytes, toGRT } from './network' +import { defaultInitArgs, Revocability, TokenLockParameters } from './config' +import { DeployOptions } from 'hardhat-deploy/types' + +const { AddressZero, MaxUint256 } = constants + +// -- Time utils -- + +const advancePeriods = async (tokenLock: GraphTokenLockWallet, n = 1) => { + const periodDuration = await tokenLock.periodDuration() + return advanceTimeAndBlock(periodDuration.mul(n).toNumber()) // advance N period +} +const advanceToStart = async (tokenLock: GraphTokenLockWallet) => moveToTime(tokenLock, await tokenLock.startTime(), 60) +const moveToTime = async (tokenLock: GraphTokenLockWallet, target: BigNumber, buffer: number) => { + const ts = await tokenLock.currentTime() + const delta = target.sub(ts).add(buffer) + return advanceTimeAndBlock(delta.toNumber()) +} + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + const [deployer] = await getAccounts() + + // Start from a fresh snapshot + await deployments.fixture([]) + + // Deploy token + await deploy('GraphTokenMock', { + from: deployer.address, + args: [toGRT('1000000000'), deployer.address], + }) + const grt = await getContract('GraphTokenMock') + + // Deploy token lock masterCopy + await deploy('GraphTokenLockWallet', { + from: deployer.address, + }) + const tokenLockWallet = await getContract('GraphTokenLockWallet') + + // Deploy token lock manager + await deploy('GraphTokenLockManager', { + from: deployer.address, + args: [grt.address, tokenLockWallet.address], + }) + const tokenLockManager = await getContract('GraphTokenLockManager') + + // Protocol contracts + await deployments.deploy('StakingMock', { from: deployer.address, args: [grt.address] }) + const staking = await getContract('StakingMock') + + // Fund the manager contract + await grt.connect(deployer.signer).transfer(tokenLockManager.address, toGRT('100000000')) + + return { + grt: grt as GraphTokenMock, + staking: staking as StakingMock, + // tokenLock: tokenLockWallet as GraphTokenLockWallet, + tokenLockManager: tokenLockManager as GraphTokenLockManager, + } +}) + +async function authProtocolFunctions(tokenLockManager: GraphTokenLockManager, stakingAddress: string) { + await tokenLockManager.setAuthFunctionCall('stake(uint256)', stakingAddress) + await tokenLockManager.setAuthFunctionCall('unstake(uint256)', stakingAddress) + await tokenLockManager.setAuthFunctionCall('withdraw()', stakingAddress) +} + +// -- Tests -- + +describe('GraphTokenLockWallet', () => { + let deployer: Account + let beneficiary: Account + let hacker: Account + + let grt: GraphTokenMock + let tokenLock: GraphTokenLockWallet + let tokenLockManager: GraphTokenLockManager + let staking: StakingMock + + let initArgs: TokenLockParameters + + const initWithArgs = async (args: TokenLockParameters): Promise => { + const tx = await tokenLockManager.createTokenLockWallet( + args.owner, + args.beneficiary, + args.managedAmount, + args.startTime, + args.endTime, + args.periods, + args.releaseStartTime, + args.vestingCliffTime, + args.revocable, + ) + const receipt = await tx.wait() + const contractAddress = receipt.events[0].args['proxy'] + return ethers.getContractAt('GraphTokenLockWallet', contractAddress) as Promise + } + + before(async function () { + [deployer, beneficiary, hacker] = await getAccounts() + }) + + beforeEach(async () => { + ({ grt, tokenLockManager, staking } = await setupTest()) + + // Setup authorized functions in Manager + await authProtocolFunctions(tokenLockManager, staking.address) + + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + tokenLock = await initWithArgs(initArgs) + }) + + describe('Init', function () { + it('should bubble up revert reasons on create', async function () { + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('35000000')) + const tx = initWithArgs({ ...initArgs, endTime: 0 }) + await expect(tx).revertedWith('Start time > end time') + }) + + // it('reject re-initialization', async function () { + // const tx = initWithArgs(initArgs) + // await expect(tx).revertedWith('Already initialized') + // }) + }) + + describe('TokenLockManager', function () { + it('revert if init with empty token', async function () { + const deploy = (name: string, options: DeployOptions) => deployments.deploy(name, options) + + const d = deploy('GraphTokenLockManager', { + from: deployer.address, + args: [AddressZero, Wallet.createRandom().address], + }) + await expect(d).revertedWith('Token cannot be zero') + }) + + it('should set the master copy', async function () { + const address = Wallet.createRandom().address + const tx = tokenLockManager.setMasterCopy(address) + await expect(tx).emit(tokenLockManager, 'MasterCopyUpdated').withArgs(address) + }) + + it('revert set the master copy to zero address', async function () { + const tx = tokenLockManager.setMasterCopy(AddressZero) + await expect(tx).revertedWith('MasterCopy cannot be zero') + }) + + it('should add a token destination', async function () { + const address = Wallet.createRandom().address + + expect(await tokenLockManager.isTokenDestination(address)).eq(false) + const tx = tokenLockManager.addTokenDestination(address) + await expect(tx).emit(tokenLockManager, 'TokenDestinationAllowed').withArgs(address, true) + expect(await tokenLockManager.isTokenDestination(address)).eq(true) + }) + + it('revert add a token destination with zero address', async function () { + const tx = tokenLockManager.addTokenDestination(AddressZero) + await expect(tx).revertedWith('Destination cannot be zero') + }) + }) + + describe('Admin wallet', function () { + it('should set manager', async function () { + // Note: we use GRT contract here just to provide a different contract + const oldManager = await tokenLock.manager() + const tx = tokenLock.connect(deployer.signer).setManager(grt.address) + await expect(tx).emit(tokenLock, 'ManagerUpdated').withArgs(oldManager, grt.address) + expect(await tokenLock.manager()).eq(grt.address) + }) + + it('reject set manager to a non-contract', async function () { + const newAddress = randomHexBytes(20) + const tx = tokenLock.connect(deployer.signer).setManager(newAddress) + await expect(tx).revertedWith('Manager must be a contract') + }) + + it('reject set manager to empty address', async function () { + const tx = tokenLock.connect(deployer.signer).setManager(AddressZero) + await expect(tx).revertedWith('Manager cannot be empty') + }) + }) + + describe('Enabling protocol', function () { + beforeEach(async function () { + await tokenLockManager.addTokenDestination(staking.address) + }) + + it('should approve protocol contracts', async function () { + const tx = tokenLock.connect(beneficiary.signer).approveProtocol() + await expect(tx).emit(grt, 'Approval').withArgs(tokenLock.address, staking.address, MaxUint256) + }) + + it('should revoke protocol contracts', async function () { + const tx = tokenLock.connect(beneficiary.signer).revokeProtocol() + await expect(tx).emit(grt, 'Approval').withArgs(tokenLock.address, staking.address, 0) + }) + + it('reject approve and revoke if not the beneficiary', async function () { + const tx1 = tokenLock.connect(deployer.signer).approveProtocol() + await expect(tx1).revertedWith('!auth') + + const tx2 = tokenLock.connect(deployer.signer).revokeProtocol() + await expect(tx2).revertedWith('!auth') + }) + }) + + describe('Function call forwarding', function () { + let lockAsStaking + + beforeEach(async () => { + // Use the tokenLock contract as if it were the Staking contract + lockAsStaking = Staking__factory.connect(tokenLock.address, deployer.signer) + + // Add the staking contract as token destination + await tokenLockManager.addTokenDestination(staking.address) + + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + }) + + it('should call an authorized function (stake)', async function () { + // Before state + const beforeLockBalance = await grt.balanceOf(lockAsStaking.address) + + // Stake must work and the deposit address must be the one of the lock contract + const stakeAmount = toGRT('100') + const tx = lockAsStaking.connect(beneficiary.signer).stake(stakeAmount) + await expect(tx).emit(staking, 'StakeDeposited').withArgs(tokenLock.address, stakeAmount) + + // After state + const afterLockBalance = await grt.balanceOf(lockAsStaking.address) + expect(afterLockBalance).eq(beforeLockBalance.sub(stakeAmount)) + }) + + it('should bubble up revert reasons for forwarded calls', async function () { + // Force a failing call + const tx = lockAsStaking.connect(beneficiary.signer).stake(toGRT('0')) + await expect(tx).revertedWith('!tokens') + }) + + it('reject a function call from other than the beneficiary', async function () { + // Send a function call from an unauthorized caller + const stakeAmount = toGRT('100') + const tx = lockAsStaking.connect(hacker.signer).stake(stakeAmount) + await expect(tx).revertedWith('Unauthorized caller') + }) + + it('reject a function call that is not authorized', async function () { + // Send a function call that is not authorized in the TokenLockManager + const tx = lockAsStaking.connect(beneficiary.signer).setController(randomHexBytes(20)) + await expect(tx).revertedWith('Unauthorized function') + }) + }) + + describe('Revokability, Call Forwarding and Used Tokens', function () { + let lockAsStaking + + beforeEach(async () => { + // Deploy a revocable contract with 6 periods, 1 per month + initArgs = defaultInitArgs(deployer, beneficiary, grt, toGRT('10000000')) + tokenLock = await initWithArgs({ ...initArgs, periods: 6, revocable: Revocability.Enabled }) + + // Use the tokenLock contract as if it were the Staking contract + lockAsStaking = Staking__factory.connect(tokenLock.address, deployer.signer) + + // Add the staking contract as token destination + await tokenLockManager.addTokenDestination(staking.address) + + // Approve contracts to pull tokens from the token lock + await tokenLock.connect(beneficiary.signer).approveProtocol() + }) + + it('reject using more than vested amount in the protocol', async function () { + await advanceToStart(tokenLock) + + // At this point no period has passed so we haven't vested any token + // Try to stake funds into the protocol should fail + const stakeAmount = toGRT('100') + const tx = lockAsStaking.connect(beneficiary.signer).stake(stakeAmount) + await expect(tx).revertedWith('Cannot use more tokens than vested amount') + }) + + it('should release considering what is used in the protocol', async function () { + // Move to have some vested periods + await advanceToStart(tokenLock) + await advancePeriods(tokenLock, 2) + + // Get amount that can be released with no used tokens yet + const releasableAmount = await tokenLock.releasableAmount() + + // Use tokens in the protocol + const stakeAmount = toGRT('100') + await lockAsStaking.connect(beneficiary.signer).stake(stakeAmount) + + // Release - should take into account used tokens + const tx = await tokenLock.connect(beneficiary.signer).release() + await expect(tx) + .emit(tokenLock, 'TokensReleased') + .withArgs(beneficiary.address, releasableAmount.sub(stakeAmount)) + + // Revoke should work + await tokenLock.connect(deployer.signer).revoke() + }) + + it('should release considering what is used in the protocol (even if most is used)', async function () { + // Move to have some vested periods + await advanceToStart(tokenLock) + await advancePeriods(tokenLock, 2) + + // Get amount that can be released with no used tokens yet + const releasableAmount = await tokenLock.releasableAmount() + + // Use tokens in the protocol + const stakeAmount = (await tokenLock.availableAmount()).sub(toGRT('1')) + await lockAsStaking.connect(beneficiary.signer).stake(stakeAmount) + + // Release - should take into account used tokens + const tx = await tokenLock.connect(beneficiary.signer).release() + await expect(tx) + .emit(tokenLock, 'TokensReleased') + .withArgs(beneficiary.address, releasableAmount.sub(stakeAmount)) + + // Revoke should work + await tokenLock.connect(deployer.signer).revoke() + }) + + it('should allow to get profit from the protocol', async function () { + await advanceToStart(tokenLock) + await advancePeriods(tokenLock, 1) + + // At this point we vested one period, we have tokens + // Stake funds into the protocol + const stakeAmount = toGRT('100') + await lockAsStaking.connect(beneficiary.signer).stake(stakeAmount) + + // Simulate having a profit + await grt.approve(staking.address, toGRT('1000000')) + await staking.stakeTo(lockAsStaking.address, toGRT('1000000')) + + // Unstake more than we used in the protocol, this should work! + await lockAsStaking.connect(beneficiary.signer).unstake(toGRT('1000000')) + await advanceBlocks(20) + await lockAsStaking.connect(beneficiary.signer).withdraw() + }) + }) +}) diff --git a/packages/token-distribution/tsconfig.json b/packages/token-distribution/tsconfig.json new file mode 100644 index 000000000..ba8d0153c --- /dev/null +++ b/packages/token-distribution/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "lib": ["ES2020", "dom"], + "module": "commonjs", + "moduleResolution": "node", + "target": "ES2020", + "outDir": "dist", + "resolveJsonModule": true, + "esModuleInterop": true + }, + "exclude": ["dist", "node_modules"], + "include": [ + ".solcover.js", + "eslint.config.js", + "prettier.config.js", + "./hardhat.config.ts", + "./scripts/**/*.ts", + "./deploy/**/*.ts", + "./test/**/*.ts", + "node_modules/@nomiclabs/hardhat-ethers/src/type-extensions.d.ts", + "node_modules/@nomiclabs/hardhat-etherscan/src/type-extensions.d.ts", + "node_modules/@nomiclabs/hardhat-waffle/src/type-extensions.d.ts", + "node_modules/hardhat-typechain/src/type-extensions.d.ts" + ] +} diff --git a/yarn.lock b/yarn.lock index 91254df50..da96ff202 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,7 +24,17 @@ __metadata: languageName: node linkType: hard -"@arbitrum/sdk@npm:^3.0.0, @arbitrum/sdk@npm:^3.1.12": +"@ampproject/remapping@npm:^2.2.0": + version: 2.2.1 + resolution: "@ampproject/remapping@npm:2.2.1" + dependencies: + "@jridgewell/gen-mapping": "npm:^0.3.0" + "@jridgewell/trace-mapping": "npm:^0.3.9" + checksum: 92ce5915f8901d8c7cd4f4e6e2fe7b9fd335a29955b400caa52e0e5b12ca3796ada7c2f10e78c9c5b0f9c2539dff0ffea7b19850a56e1487aa083531e1e46d43 + languageName: node + linkType: hard + +"@arbitrum/sdk@npm:~3.1.13": version: 3.1.13 resolution: "@arbitrum/sdk@npm:3.1.13" dependencies: @@ -37,6 +47,58 @@ __metadata: languageName: node linkType: hard +"@ardatan/fast-json-stringify@npm:^0.0.6": + version: 0.0.6 + resolution: "@ardatan/fast-json-stringify@npm:0.0.6" + dependencies: + "@fastify/deepmerge": "npm:^1.0.0" + fast-deep-equal: "npm:^3.1.3" + rfdc: "npm:^1.2.0" + peerDependencies: + ajv: ^8.10.0 + ajv-formats: ^2.1.1 + checksum: 45f4f60c2b8d91a2b53a51c8785f4bcf6eeff3fad361a1b5c351ae0c45c2b224e8a3cb358e3445d31bf57f0a1ac04cb2282dd4b1b053cac8a2c081a22d306b26 + languageName: node + linkType: hard + +"@ardatan/relay-compiler@npm:12.0.0": + version: 12.0.0 + resolution: "@ardatan/relay-compiler@npm:12.0.0" + dependencies: + "@babel/core": "npm:^7.14.0" + "@babel/generator": "npm:^7.14.0" + "@babel/parser": "npm:^7.14.0" + "@babel/runtime": "npm:^7.0.0" + "@babel/traverse": "npm:^7.14.0" + "@babel/types": "npm:^7.0.0" + babel-preset-fbjs: "npm:^3.4.0" + chalk: "npm:^4.0.0" + fb-watchman: "npm:^2.0.0" + fbjs: "npm:^3.0.0" + glob: "npm:^7.1.1" + immutable: "npm:~3.7.6" + invariant: "npm:^2.2.4" + nullthrows: "npm:^1.1.1" + relay-runtime: "npm:12.0.0" + signedsource: "npm:^1.0.0" + yargs: "npm:^15.3.1" + peerDependencies: + graphql: "*" + bin: + relay-compiler: bin/relay-compiler + checksum: 7207d65dd39d3a6202fcee81b03338409642a0ff4e7f799b4a074025429ce2b17b6c71c9579a6328b0f4548763ba4efbff0436cddbcad934af00cc4dbc7ac4e1 + languageName: node + linkType: hard + +"@ardatan/sync-fetch@npm:^0.0.1": + version: 0.0.1 + resolution: "@ardatan/sync-fetch@npm:0.0.1" + dependencies: + node-fetch: "npm:^2.6.1" + checksum: cd69134005ef5ea570d55631c8be59b593e2dda2207f616d30618f948af6ee5d227b857aefd56c535e8f7f3ade47083e4e7795b5ee014a6732011c6e5f9eb08f + languageName: node + linkType: hard + "@aws-crypto/sha256-js@npm:1.2.2": version: 1.2.2 resolution: "@aws-crypto/sha256-js@npm:1.2.2" @@ -60,12 +122,12 @@ __metadata: linkType: hard "@aws-sdk/types@npm:^3.1.0": - version: 3.460.0 - resolution: "@aws-sdk/types@npm:3.460.0" + version: 3.515.0 + resolution: "@aws-sdk/types@npm:3.515.0" dependencies: - "@smithy/types": "npm:^2.5.0" + "@smithy/types": "npm:^2.9.1" tslib: "npm:^2.5.0" - checksum: 95a09dd069ed6269ce16f34adba074704d5963efaf9fa974401c201acf9cf7c947286ee5509a3ac91cfb7c36c8926673deedba71359c3a9c856317a76f43cb21 + checksum: 47afecf060dec7e7db5073dfec7d6815582f66266cfb31111af4a80fc10bc56bf5c7a5dc096780849efa982a9b097e69b1b3bebf23d82521763b04ae17cc7202 languageName: node linkType: hard @@ -78,1644 +140,3477 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:7.12.11": - version: 7.12.11 - resolution: "@babel/code-frame@npm:7.12.11" - dependencies: - "@babel/highlight": "npm:^7.10.4" - checksum: 836ffd155506768e991d6dd8c51db37cad5958ed1c8e0a2329ccd9527165d5c752e943d66a5c3c92ffd45f343419f0742e7636629a529f4fbd5303e3637746b9 - languageName: node - linkType: hard - -"@babel/code-frame@npm:^7.0.0": - version: 7.23.4 - resolution: "@babel/code-frame@npm:7.23.4" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" dependencies: "@babel/highlight": "npm:^7.23.4" chalk: "npm:^2.4.2" - checksum: 2ef6f5e10004c4e8b755961b68570db0ea556ccb17a37c13a7f1fed1f4e273aed6c1ae1fcb86abb991620d8be083e1472a7ea5429f05bc342de54c027b07ea83 + checksum: a10e843595ddd9f97faa99917414813c06214f4d9205294013e20c70fbdf4f943760da37dec1d998bf3e6fc20fa2918a47c0e987a7e458663feb7698063ad7c6 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: dcad63db345fb110e032de46c3688384b0008a42a4845180ce7cd62b1a9c0507a1bed727c4d1060ed1a03ae57b4d918570259f81724aaac1a5b776056f37504e +"@babel/compat-data@npm:^7.20.5, @babel/compat-data@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/compat-data@npm:7.23.5" + checksum: 081278ed46131a890ad566a59c61600a5f9557bd8ee5e535890c8548192532ea92590742fd74bd9db83d74c669ef8a04a7e1c85cdea27f960233e3b83c3a957c languageName: node linkType: hard -"@babel/highlight@npm:^7.10.4, @babel/highlight@npm:^7.23.4": - version: 7.23.4 - resolution: "@babel/highlight@npm:7.23.4" +"@babel/core@npm:^7.14.0": + version: 7.23.9 + resolution: "@babel/core@npm:7.23.9" dependencies: - "@babel/helper-validator-identifier": "npm:^7.22.20" - chalk: "npm:^2.4.2" - js-tokens: "npm:^4.0.0" - checksum: fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 + "@ampproject/remapping": "npm:^2.2.0" + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.6" + "@babel/helper-compilation-targets": "npm:^7.23.6" + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helpers": "npm:^7.23.9" + "@babel/parser": "npm:^7.23.9" + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + convert-source-map: "npm:^2.0.0" + debug: "npm:^4.1.0" + gensync: "npm:^1.0.0-beta.2" + json5: "npm:^2.2.3" + semver: "npm:^6.3.1" + checksum: 03883300bf1252ab4c9ba5b52f161232dd52873dbe5cde9289bb2bb26e935c42682493acbac9194a59a3b6cbd17f4c4c84030db8d6d482588afe64531532ff9b languageName: node linkType: hard -"@chainsafe/as-sha256@npm:^0.3.1": - version: 0.3.1 - resolution: "@chainsafe/as-sha256@npm:0.3.1" - checksum: 72561fc6552a53e4d1fc28880b7f82ecb7a997670568333cb479f323db9482a6a59dd9d0f915210703e51c3a4ca2701ccdb4c66a0202abab4872d81184c9212e +"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/generator@npm:7.23.6" + dependencies: + "@babel/types": "npm:^7.23.6" + "@jridgewell/gen-mapping": "npm:^0.3.2" + "@jridgewell/trace-mapping": "npm:^0.3.17" + jsesc: "npm:^2.5.1" + checksum: 53540e905cd10db05d9aee0a5304e36927f455ce66f95d1253bb8a179f286b88fa7062ea0db354c566fe27f8bb96567566084ffd259f8feaae1de5eccc8afbda languageName: node linkType: hard -"@chainsafe/persistent-merkle-tree@npm:^0.4.2": - version: 0.4.2 - resolution: "@chainsafe/persistent-merkle-tree@npm:0.4.2" +"@babel/helper-annotate-as-pure@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-annotate-as-pure@npm:7.22.5" dependencies: - "@chainsafe/as-sha256": "npm:^0.3.1" - checksum: 9533e478a1a990e8cf8710a2eeb84c6f08c7b61726a43dbe2165316256839c29a2ff17923bce5e5effec446d832de8b0a5bc896ef5db80bce059af5d1bd20d8d + "@babel/types": "npm:^7.22.5" + checksum: 5a80dc364ddda26b334bbbc0f6426cab647381555ef7d0cd32eb284e35b867c012ce6ce7d52a64672ed71383099c99d32765b3d260626527bb0e3470b0f58e45 languageName: node linkType: hard -"@chainsafe/persistent-merkle-tree@npm:^0.5.0": - version: 0.5.0 - resolution: "@chainsafe/persistent-merkle-tree@npm:0.5.0" +"@babel/helper-compilation-targets@npm:^7.20.7, @babel/helper-compilation-targets@npm:^7.22.15, @babel/helper-compilation-targets@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/helper-compilation-targets@npm:7.23.6" dependencies: - "@chainsafe/as-sha256": "npm:^0.3.1" - checksum: 73c7a7536f49aceab61870fcc1dafef8a8be2ae0bfff2614846bb4b57a21939da75bca7bc5d1959cd312a5133be0acaf0e30fb323410c57592e9ec384758efe0 + "@babel/compat-data": "npm:^7.23.5" + "@babel/helper-validator-option": "npm:^7.23.5" + browserslist: "npm:^4.22.2" + lru-cache: "npm:^5.1.1" + semver: "npm:^6.3.1" + checksum: ba38506d11185f48b79abf439462ece271d3eead1673dd8814519c8c903c708523428806f05f2ec5efd0c56e4e278698fac967e5a4b5ee842c32415da54bc6fa languageName: node linkType: hard -"@chainsafe/ssz@npm:^0.10.0": - version: 0.10.2 - resolution: "@chainsafe/ssz@npm:0.10.2" +"@babel/helper-create-class-features-plugin@npm:^7.18.6": + version: 7.23.10 + resolution: "@babel/helper-create-class-features-plugin@npm:7.23.10" dependencies: - "@chainsafe/as-sha256": "npm:^0.3.1" - "@chainsafe/persistent-merkle-tree": "npm:^0.5.0" - checksum: be427eba9f9c4a542326f9f3c20eb704c1c2500c4f124ba18febf6ffd5bb7bd5755228d99326bf6c4e4d969daa4b6ff2efb743688ec36ef86f20c0c673c0e967 + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-member-expression-to-functions": "npm:^7.23.0" + "@babel/helper-optimise-call-expression": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.20" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + semver: "npm:^6.3.1" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: f30437aa16f3585cc3382ea630f24457ef622c22f5e4eccffbc03f6a81efbef0b6714fb5a78baa64c838884ba7e1427e3280d7b27481b9f587bc8fbbed05dd36 languageName: node linkType: hard -"@chainsafe/ssz@npm:^0.9.2": - version: 0.9.4 - resolution: "@chainsafe/ssz@npm:0.9.4" - dependencies: - "@chainsafe/as-sha256": "npm:^0.3.1" - "@chainsafe/persistent-merkle-tree": "npm:^0.4.2" - case: "npm:^1.6.3" - checksum: 4ce4b867c60dbee98772fe075037c7ef9a7894f97a4fb04f3cfd57e11fa683b8c23a4d80b53592d10fbd4e2abac43c9099181cfaee587619366f49091b9e5fcb +"@babel/helper-environment-visitor@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-environment-visitor@npm:7.22.20" + checksum: e762c2d8f5d423af89bd7ae9abe35bd4836d2eb401af868a63bbb63220c513c783e25ef001019418560b3fdc6d9a6fb67e6c0b650bcdeb3a2ac44b5c3d2bdd94 languageName: node linkType: hard -"@colors/colors@npm:1.5.0": - version: 1.5.0 - resolution: "@colors/colors@npm:1.5.0" - checksum: eb42729851adca56d19a08e48d5a1e95efd2a32c55ae0323de8119052be0510d4b7a1611f2abcbf28c044a6c11e6b7d38f99fccdad7429300c37a8ea5fb95b44 +"@babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" + dependencies: + "@babel/template": "npm:^7.22.15" + "@babel/types": "npm:^7.23.0" + checksum: d771dd1f3222b120518176733c52b7cadac1c256ff49b1889dbbe5e3fed81db855b8cc4e40d949c9d3eae0e795e8229c1c8c24c0e83f27cfa6ee3766696c6428 languageName: node linkType: hard -"@colors/colors@npm:1.6.0, @colors/colors@npm:^1.6.0": - version: 1.6.0 - resolution: "@colors/colors@npm:1.6.0" - checksum: 9328a0778a5b0db243af54455b79a69e3fb21122d6c15ef9e9fcc94881d8d17352d8b2b2590f9bdd46fac5c2d6c1636dcfc14358a20c70e22daf89e1a759b629 +"@babel/helper-hoist-variables@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-hoist-variables@npm:7.22.5" + dependencies: + "@babel/types": "npm:^7.22.5" + checksum: 60a3077f756a1cd9f14eb89f0037f487d81ede2b7cfe652ea6869cd4ec4c782b0fb1de01b8494b9a2d2050e3d154d7d5ad3be24806790acfb8cbe2073bf1e208 languageName: node linkType: hard -"@commitlint/cli@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/cli@npm:18.4.3" - dependencies: - "@commitlint/format": "npm:^18.4.3" - "@commitlint/lint": "npm:^18.4.3" - "@commitlint/load": "npm:^18.4.3" - "@commitlint/read": "npm:^18.4.3" - "@commitlint/types": "npm:^18.4.3" - execa: "npm:^5.0.0" - lodash.isfunction: "npm:^3.0.9" - resolve-from: "npm:5.0.0" - resolve-global: "npm:1.0.0" - yargs: "npm:^17.0.0" - bin: - commitlint: cli.js - checksum: c412eada9d27444c73703c7e8365c3be3ea9b0e7ac76b670c1b7afbec3d65f420a2c68c75255112c7a4fb2575cb61ead9c809dd67862b4f8c0bc76f68aa79022 +"@babel/helper-member-expression-to-functions@npm:^7.22.15, @babel/helper-member-expression-to-functions@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0" + dependencies: + "@babel/types": "npm:^7.23.0" + checksum: b810daddf093ffd0802f1429052349ed9ea08ef7d0c56da34ffbcdecbdafac86f95bdea2fe30e0e0e629febc7dd41b56cb5eacc10d1a44336d37b755dac31fa4 languageName: node linkType: hard -"@commitlint/config-conventional@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/config-conventional@npm:18.4.3" +"@babel/helper-module-imports@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-module-imports@npm:7.22.15" dependencies: - conventional-changelog-conventionalcommits: "npm:^7.0.2" - checksum: 13977d8c9cbac31c172ead77c36da5fd88c980438a9811e2b5447f994442200daf8d2d37c5ffef9f5b6afef100513a2ac1e3ec94ba667d7a62fce117e57a16b1 + "@babel/types": "npm:^7.22.15" + checksum: 4e0d7fc36d02c1b8c8b3006dfbfeedf7a367d3334a04934255de5128115ea0bafdeb3e5736a2559917f0653e4e437400d54542da0468e08d3cbc86d3bbfa8f30 languageName: node linkType: hard -"@commitlint/config-validator@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/config-validator@npm:18.4.3" +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" dependencies: - "@commitlint/types": "npm:^18.4.3" - ajv: "npm:^8.11.0" - checksum: 8e6f3130a2e9c17c08276fc81b16e70320af27718bfdfc954e5a591538a23f9510bbbf61f60499d5e09488f112df9400730f065c7309006a9e9da7bd1d371385 + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-module-imports": "npm:^7.22.15" + "@babel/helper-simple-access": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/helper-validator-identifier": "npm:^7.22.20" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 211e1399d0c4993671e8e5c2b25383f08bee40004ace5404ed4065f0e9258cc85d99c1b82fd456c030ce5cfd4d8f310355b54ef35de9924eabfc3dff1331d946 languageName: node linkType: hard -"@commitlint/ensure@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/ensure@npm:18.4.3" +"@babel/helper-optimise-call-expression@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" dependencies: - "@commitlint/types": "npm:^18.4.3" - lodash.camelcase: "npm:^4.3.0" - lodash.kebabcase: "npm:^4.1.1" - lodash.snakecase: "npm:^4.1.1" - lodash.startcase: "npm:^4.4.0" - lodash.upperfirst: "npm:^4.3.1" - checksum: 6aa2dfffcd89d02f9e2bbec068ce88830406d9fe6f022c06c1c301f8bd6eb683a5cd3294707e1bdc56251e413e9ab79d359ad766be9a3cc896c6830d3ffc4dff + "@babel/types": "npm:^7.22.5" + checksum: 31b41a764fc3c585196cf5b776b70cf4705c132e4ce9723f39871f215f2ddbfb2e28a62f9917610f67c8216c1080482b9b05f65dd195dae2a52cef461f2ac7b8 languageName: node linkType: hard -"@commitlint/execute-rule@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/execute-rule@npm:18.4.3" - checksum: 6a0514733c3fab7279b4831df58f518b98c589d05eace2d9b5f1f64d05f9f1493af51f3b6004df4f90e794b98798ee07cf4c5fbe9e97f37d5437a50cd56bf52f +"@babel/helper-plugin-utils@npm:^7.12.13, @babel/helper-plugin-utils@npm:^7.18.6, @babel/helper-plugin-utils@npm:^7.20.2, @babel/helper-plugin-utils@npm:^7.22.5, @babel/helper-plugin-utils@npm:^7.8.0": + version: 7.22.5 + resolution: "@babel/helper-plugin-utils@npm:7.22.5" + checksum: d2c4bfe2fa91058bcdee4f4e57a3f4933aed7af843acfd169cd6179fab8d13c1d636474ecabb2af107dc77462c7e893199aa26632bac1c6d7e025a17cbb9d20d languageName: node linkType: hard -"@commitlint/format@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/format@npm:18.4.3" +"@babel/helper-replace-supers@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-replace-supers@npm:7.22.20" dependencies: - "@commitlint/types": "npm:^18.4.3" - chalk: "npm:^4.1.0" - checksum: c2ed05e17f2038af79b39ec0d5bd74d42c2ddd9da4eee22ca372414625084b34f69b24e9372c00a3eb061364a258e1a6eb43f9def38ef6e7995606459d900f15 + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-member-expression-to-functions": "npm:^7.22.15" + "@babel/helper-optimise-call-expression": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 6b0858811ad46873817c90c805015d63300e003c5a85c147a17d9845fa2558a02047c3cc1f07767af59014b2dd0fa75b503e5bc36e917f360e9b67bb6f1e79f4 languageName: node linkType: hard -"@commitlint/is-ignored@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/is-ignored@npm:18.4.3" +"@babel/helper-simple-access@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-simple-access@npm:7.22.5" dependencies: - "@commitlint/types": "npm:^18.4.3" - semver: "npm:7.5.4" - checksum: 9b2456e0b31656eb1c2828d6a4c0ec12815bfb88e734bc673315a08a6ef5b19e96ecd0cc925d88b797bafe4c09a3aca7d5841c02f8e5de4cc88473bbfba1a275 + "@babel/types": "npm:^7.22.5" + checksum: f0cf81a30ba3d09a625fd50e5a9069e575c5b6719234e04ee74247057f8104beca89ed03e9217b6e9b0493434cedc18c5ecca4cea6244990836f1f893e140369 languageName: node linkType: hard -"@commitlint/lint@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/lint@npm:18.4.3" +"@babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5" dependencies: - "@commitlint/is-ignored": "npm:^18.4.3" - "@commitlint/parse": "npm:^18.4.3" - "@commitlint/rules": "npm:^18.4.3" - "@commitlint/types": "npm:^18.4.3" - checksum: c5b7c8296db1973784d8642148bbdb7f75f9edc6700eafb4c1b1be57706ce79188e95da834742d4559430000ba640b80a0b90a92aa3555c4948155f2358ceaa0 + "@babel/types": "npm:^7.22.5" + checksum: ab7fa2aa709ab49bb8cd86515a1e715a3108c4bb9a616965ba76b43dc346dee66d1004ccf4d222b596b6224e43e04cbc5c3a34459501b388451f8c589fbc3691 languageName: node linkType: hard -"@commitlint/load@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/load@npm:18.4.3" +"@babel/helper-split-export-declaration@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helper-split-export-declaration@npm:7.22.6" dependencies: - "@commitlint/config-validator": "npm:^18.4.3" - "@commitlint/execute-rule": "npm:^18.4.3" - "@commitlint/resolve-extends": "npm:^18.4.3" - "@commitlint/types": "npm:^18.4.3" - "@types/node": "npm:^18.11.9" - chalk: "npm:^4.1.0" - cosmiconfig: "npm:^8.3.6" - cosmiconfig-typescript-loader: "npm:^5.0.0" - lodash.isplainobject: "npm:^4.0.6" - lodash.merge: "npm:^4.6.2" - lodash.uniq: "npm:^4.5.0" - resolve-from: "npm:^5.0.0" - checksum: e40a8cb162603b9e01f4216c643314364cfbe7a68eab8ff30bb90eaf67ac9dacafc51f6f608ff8e45639877d8ce2441fd1744b85d551d00e55cefa0797bebefb + "@babel/types": "npm:^7.22.5" + checksum: d83e4b623eaa9622c267d3c83583b72f3aac567dc393dda18e559d79187961cb29ae9c57b2664137fc3d19508370b12ec6a81d28af73a50e0846819cb21c6e44 languageName: node linkType: hard -"@commitlint/message@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/message@npm:18.4.3" - checksum: 24b373d5c99230351a31294e974ee338cbac45094c66a6ba9ce00357783f7ebb250fc169fcdd815c8d510951757119fbd1329e7ab9e3097d3e732768d3d93787 +"@babel/helper-string-parser@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/helper-string-parser@npm:7.23.4" + checksum: f348d5637ad70b6b54b026d6544bd9040f78d24e7ec245a0fc42293968181f6ae9879c22d89744730d246ce8ec53588f716f102addd4df8bbc79b73ea10004ac languageName: node linkType: hard -"@commitlint/parse@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/parse@npm:18.4.3" - dependencies: - "@commitlint/types": "npm:^18.4.3" - conventional-changelog-angular: "npm:^7.0.0" - conventional-commits-parser: "npm:^5.0.0" - checksum: ce25e90a9f0920ce8bd1bf9a56ca250394b60d5c63d5fb9e41e047c64f8278ecfffc121a872662dead80dbcc4c3afaf3b80f93e89e8f8ca1d5f05ff0f145813c +"@babel/helper-validator-identifier@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-validator-identifier@npm:7.22.20" + checksum: dcad63db345fb110e032de46c3688384b0008a42a4845180ce7cd62b1a9c0507a1bed727c4d1060ed1a03ae57b4d918570259f81724aaac1a5b776056f37504e languageName: node linkType: hard -"@commitlint/read@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/read@npm:18.4.3" - dependencies: - "@commitlint/top-level": "npm:^18.4.3" - "@commitlint/types": "npm:^18.4.3" - fs-extra: "npm:^11.0.0" - git-raw-commits: "npm:^2.0.11" - minimist: "npm:^1.2.6" - checksum: 35621e5aeb5234c01e98bf30bdf7c6b5e710d7fcfe4e75a6708e64157160344c3ea1ebc4dc82b49b590909daa0a8258e489e3f8c70c56a96a0b884d7d724f01a +"@babel/helper-validator-option@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/helper-validator-option@npm:7.23.5" + checksum: af45d5c0defb292ba6fd38979e8f13d7da63f9623d8ab9ededc394f67eb45857d2601278d151ae9affb6e03d5d608485806cd45af08b4468a0515cf506510e94 languageName: node linkType: hard -"@commitlint/resolve-extends@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/resolve-extends@npm:18.4.3" +"@babel/helpers@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/helpers@npm:7.23.9" dependencies: - "@commitlint/config-validator": "npm:^18.4.3" - "@commitlint/types": "npm:^18.4.3" - import-fresh: "npm:^3.0.0" - lodash.mergewith: "npm:^4.6.2" - resolve-from: "npm:^5.0.0" - resolve-global: "npm:^1.0.0" - checksum: cf90d48e5111a43778036a2bd80f16f96a32acac222bdee14a6c66a9fab0406626fe2ac2a89cc1862f17568b49b9e8ed1acea2b193e83c92d5e7a8369e41b988 + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: f69fd0aca96a6fb8bd6dd044cd8a5c0f1851072d4ce23355345b9493c4032e76d1217f86b70df795e127553cf7f3fcd1587ede9d1b03b95e8b62681ca2165b87 languageName: node linkType: hard -"@commitlint/rules@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/rules@npm:18.4.3" +"@babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" dependencies: - "@commitlint/ensure": "npm:^18.4.3" - "@commitlint/message": "npm:^18.4.3" - "@commitlint/to-lines": "npm:^18.4.3" - "@commitlint/types": "npm:^18.4.3" - execa: "npm:^5.0.0" - checksum: 7d24dd1c024be232d9acd2f61bbbd5302f87acb3ad9fceebeedd80bf8e00821194a636faaefe1a1cd3f14330eb5f18a9bca58981ce9b348e2fb8723a4a72cd5c + "@babel/helper-validator-identifier": "npm:^7.22.20" + chalk: "npm:^2.4.2" + js-tokens: "npm:^4.0.0" + checksum: fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 languageName: node linkType: hard -"@commitlint/to-lines@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/to-lines@npm:18.4.3" - checksum: a163a647ebcdc9fb8a84f3406f92fde78b90cc73146c367367806d52022c6b6219b78f5b0afea0faab357f95b9e311822bc9309a0148fd31f30bdb77bfcfd84a +"@babel/parser@npm:^7.14.0, @babel/parser@npm:^7.16.8, @babel/parser@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/parser@npm:7.23.9" + bin: + parser: ./bin/babel-parser.js + checksum: 7df97386431366d4810538db4b9ec538f4377096f720c0591c7587a16f6810e62747e9fbbfa1ff99257fd4330035e4fb1b5b77c7bd3b97ce0d2e3780a6618975 languageName: node linkType: hard -"@commitlint/top-level@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/top-level@npm:18.4.3" +"@babel/plugin-proposal-class-properties@npm:^7.0.0": + version: 7.18.6 + resolution: "@babel/plugin-proposal-class-properties@npm:7.18.6" dependencies: - find-up: "npm:^5.0.0" - checksum: 69a75878a18ba812e12be899c3b032c1067d093261e7c622f18a3110bc83483d75fa9c2a589086590a9896d389b407cc58d324803821c314bf952912f57b0095 + "@babel/helper-create-class-features-plugin": "npm:^7.18.6" + "@babel/helper-plugin-utils": "npm:^7.18.6" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: d5172ac6c9948cdfc387e94f3493ad86cb04035cf7433f86b5d358270b1b9752dc25e176db0c5d65892a246aca7bdb4636672e15626d7a7de4bc0bd0040168d9 languageName: node linkType: hard -"@commitlint/types@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/types@npm:18.4.3" +"@babel/plugin-proposal-object-rest-spread@npm:^7.0.0": + version: 7.20.7 + resolution: "@babel/plugin-proposal-object-rest-spread@npm:7.20.7" dependencies: - chalk: "npm:^4.1.0" - checksum: 07cbc4b5eb813052401d9e332c0dadca7864cd22eddd06edb6afd1da212243d505c4429ce100012c4086ea99d0f4a4086382fc88e3e662c6577e69d638c3903e + "@babel/compat-data": "npm:^7.20.5" + "@babel/helper-compilation-targets": "npm:^7.20.7" + "@babel/helper-plugin-utils": "npm:^7.20.2" + "@babel/plugin-syntax-object-rest-spread": "npm:^7.8.3" + "@babel/plugin-transform-parameters": "npm:^7.20.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b9818749bb49d8095df64c45db682448d04743d96722984cbfd375733b2585c26d807f84b4fdb28474f2d614be6a6ffe3d96ffb121840e9e5345b2ccc0438bd8 languageName: node linkType: hard -"@cspotcode/source-map-support@npm:^0.8.0": - version: 0.8.1 - resolution: "@cspotcode/source-map-support@npm:0.8.1" +"@babel/plugin-syntax-class-properties@npm:^7.0.0": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" dependencies: - "@jridgewell/trace-mapping": "npm:0.3.9" - checksum: 05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 + "@babel/helper-plugin-utils": "npm:^7.12.13" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 95168fa186416195280b1264fb18afcdcdcea780b3515537b766cb90de6ce042d42dd6a204a39002f794ae5845b02afb0fd4861a3308a861204a55e68310a120 languageName: node linkType: hard -"@dabh/diagnostics@npm:^2.0.2": - version: 2.0.3 - resolution: "@dabh/diagnostics@npm:2.0.3" +"@babel/plugin-syntax-flow@npm:^7.0.0, @babel/plugin-syntax-flow@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-flow@npm:7.23.3" dependencies: - colorspace: "npm:1.1.x" - enabled: "npm:2.0.x" - kuler: "npm:^2.0.0" - checksum: a5133df8492802465ed01f2f0a5784585241a1030c362d54a602ed1839816d6c93d71dde05cf2ddb4fd0796238c19774406bd62fa2564b637907b495f52425fe + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8a5e1e8b6a3728a2c8fe6d70c09a43642e737d9c0485e1b041cd3a6021ef05376ec3c9137be3b118c622ba09b5770d26fdc525473f8d06d4ab9e46de2783dd0a languageName: node linkType: hard -"@defi-wonderland/smock@npm:^2.0.7": - version: 2.3.5 - resolution: "@defi-wonderland/smock@npm:2.3.5" +"@babel/plugin-syntax-import-assertions@npm:^7.20.0": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.23.3" dependencies: - "@nomicfoundation/ethereumjs-evm": "npm:^1.0.0-rc.3" - "@nomicfoundation/ethereumjs-util": "npm:^8.0.0-rc.3" - "@nomicfoundation/ethereumjs-vm": "npm:^6.0.0-rc.3" - diff: "npm:^5.0.0" - lodash.isequal: "npm:^4.5.0" - lodash.isequalwith: "npm:^4.4.0" - rxjs: "npm:^7.2.0" - semver: "npm:^7.3.5" + "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: - "@ethersproject/abi": ^5 - "@ethersproject/abstract-provider": ^5 - "@ethersproject/abstract-signer": ^5 - "@nomiclabs/hardhat-ethers": ^2 - ethers: ^5 - hardhat: ^2 - checksum: c831563fe6607841d69f5936011398a492f760f52f9cb17626b2949ff3ef7668729acc4a3a944f739417b2d1b99bc6c83580f236189f27431224021c66ac1821 + "@babel/core": ^7.0.0-0 + checksum: 7db8b59f75667bada2293353bb66b9d5651a673b22c72f47da9f5c46e719142481601b745f9822212fd7522f92e26e8576af37116f85dae1b5e5967f80d0faab languageName: node linkType: hard -"@ensdomains/ens@npm:^0.4.4": - version: 0.4.5 - resolution: "@ensdomains/ens@npm:0.4.5" +"@babel/plugin-syntax-jsx@npm:^7.0.0, @babel/plugin-syntax-jsx@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/plugin-syntax-jsx@npm:7.23.3" dependencies: - bluebird: "npm:^3.5.2" - eth-ens-namehash: "npm:^2.0.8" - solc: "npm:^0.4.20" - testrpc: "npm:0.0.1" - web3-utils: "npm:^1.0.0-beta.31" - checksum: 15a77b5db73550546e6684cb6f8105170c9c113e3dc128ee718eabd3c2b1d13fdeb5791fa79c7b149b5b83b6e00040b7320c27796b7970fae66e8d3e5cce6561 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 563bb7599b868773f1c7c1d441ecc9bc53aeb7832775da36752c926fc402a1fa5421505b39e724f71eb217c13e4b93117e081cac39723b0e11dac4c897f33c3e languageName: node linkType: hard -"@ensdomains/resolver@npm:^0.2.4": - version: 0.2.4 - resolution: "@ensdomains/resolver@npm:0.2.4" - checksum: 8bd21f82c3f122f56d7198cf671c08204cca2cb531fd5074fd558d625afa8a15828e92738bf80b9961575a92e4fe627208edd3f87a04c6a0fa47531c91ef0639 +"@babel/plugin-syntax-object-rest-spread@npm:^7.0.0, @babel/plugin-syntax-object-rest-spread@npm:^7.8.3": + version: 7.8.3 + resolution: "@babel/plugin-syntax-object-rest-spread@npm:7.8.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ee1eab52ea6437e3101a0a7018b0da698545230015fc8ab129d292980ec6dff94d265e9e90070e8ae5fed42f08f1622c14c94552c77bcac784b37f503a82ff26 languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": - version: 4.4.0 - resolution: "@eslint-community/eslint-utils@npm:4.4.0" +"@babel/plugin-transform-arrow-functions@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.23.3" dependencies: - eslint-visitor-keys: "npm:^3.3.0" + "@babel/helper-plugin-utils": "npm:^7.22.5" peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 7e559c4ce59cd3a06b1b5a517b593912e680a7f981ae7affab0d01d709e99cd5647019be8fafa38c350305bc32f1f7d42c7073edde2ab536c745e365f37b607e + "@babel/core": ^7.0.0-0 + checksum: b128315c058f5728d29b0b78723659b11de88247ea4d0388f0b935cddf60a80c40b9067acf45cbbe055bd796928faef152a09d9e4a0695465aca4394d9f109ca languageName: node linkType: hard -"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": - version: 4.10.0 - resolution: "@eslint-community/regexpp@npm:4.10.0" - checksum: c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 +"@babel/plugin-transform-block-scoped-functions@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-block-scoped-functions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 82c12a11277528184a979163de7189ceb00129f60dd930b0d5313454310bf71205f302fb2bf0430247161c8a22aaa9fb9eec1459f9f7468206422c191978fd59 languageName: node linkType: hard -"@eslint/eslintrc@npm:^0.4.3": - version: 0.4.3 - resolution: "@eslint/eslintrc@npm:0.4.3" +"@babel/plugin-transform-block-scoping@npm:^7.0.0": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" dependencies: - ajv: "npm:^6.12.4" - debug: "npm:^4.1.1" - espree: "npm:^7.3.0" - globals: "npm:^13.9.0" - ignore: "npm:^4.0.6" - import-fresh: "npm:^3.2.1" - js-yaml: "npm:^3.13.1" - minimatch: "npm:^3.0.4" - strip-json-comments: "npm:^3.1.1" - checksum: 0eed93369f72ef044686d07824742121f9b95153ff34f4614e4e69d64332ee68c84eb70da851a9005bb76b3d1d64ad76c2e6293a808edc0f7dfb883689ca136d + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 83006804dddf980ab1bcd6d67bc381e24b58c776507c34f990468f820d0da71dba3697355ca4856532fa2eeb2a1e3e73c780f03760b5507a511cbedb0308e276 languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.3": - version: 2.1.3 - resolution: "@eslint/eslintrc@npm:2.1.3" +"@babel/plugin-transform-classes@npm:^7.0.0": + version: 7.23.8 + resolution: "@babel/plugin-transform-classes@npm:7.23.8" dependencies: - ajv: "npm:^6.12.4" - debug: "npm:^4.3.2" - espree: "npm:^9.6.0" - globals: "npm:^13.19.0" - ignore: "npm:^5.2.0" - import-fresh: "npm:^3.2.1" - js-yaml: "npm:^4.1.0" - minimatch: "npm:^3.1.2" - strip-json-comments: "npm:^3.1.1" - checksum: f4103f4346126292eb15581c5a1d12bef03410fd3719dedbdb92e1f7031d46a5a2d60de8566790445d5d4b70b75ba050876799a11f5fff8265a91ee3fa77dab0 + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-compilation-targets": "npm:^7.23.6" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.20" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + globals: "npm:^11.1.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 227ac5166501e04d9e7fbd5eda6869b084ffa4af6830ac12544ac6ea14953ca00eb1762b0df9349c0f6c8d2a799385910f558066cd0fb85b9ca437b1131a6043 languageName: node linkType: hard -"@eslint/js@npm:8.54.0": - version: 8.54.0 - resolution: "@eslint/js@npm:8.54.0" - checksum: d61fb4a0be6af2d8cb290121c329697664a75d6255a29926d5454fb02aeb02b87112f67fdf218d10abac42f90c570ac366126751baefc5405d0e017ed0c946c5 +"@babel/plugin-transform-computed-properties@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-computed-properties@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/template": "npm:^7.22.15" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3ca8a006f8e652b58c21ecb84df1d01a73f0a96b1d216fd09a890b235dd90cb966b152b603b88f7e850ae238644b1636ce5c30b7c029c0934b43383932372e4a languageName: node linkType: hard -"@ethereum-waffle/chai@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/chai@npm:3.4.4" +"@babel/plugin-transform-destructuring@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-destructuring@npm:7.23.3" dependencies: - "@ethereum-waffle/provider": "npm:^3.4.4" - ethers: "npm:^5.5.2" - checksum: 69921adf1d2320e853f7d61b8ce2cf45cdba746666097dc59f7578b22374f821b245e88368c563f3fa58c32d14c981d6025342a90a3cbc005ef84afc87fee807 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 717e9a62c1b0c93c507f87b4eaf839ec08d3c3147f14d74ae240d8749488d9762a8b3950132be620a069bde70f4b3e4ee9867b226c973fcc40f3cdec975cde71 languageName: node linkType: hard -"@ethereum-waffle/compiler@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/compiler@npm:3.4.4" +"@babel/plugin-transform-flow-strip-types@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-flow-strip-types@npm:7.23.3" dependencies: - "@resolver-engine/imports": "npm:^0.3.3" - "@resolver-engine/imports-fs": "npm:^0.3.3" - "@typechain/ethers-v5": "npm:^2.0.0" - "@types/mkdirp": "npm:^0.5.2" - "@types/node-fetch": "npm:^2.5.5" - ethers: "npm:^5.0.1" - mkdirp: "npm:^0.5.1" - node-fetch: "npm:^2.6.1" - solc: "npm:^0.6.3" - ts-generator: "npm:^0.1.1" - typechain: "npm:^3.0.0" - checksum: ea54d5e0094fc74ac4ae70d4149f5ee939ff265315ea851615f169447b94aabacb56567e6477518e24758e767084aab8c4ec089ad9442a6a742c279f5883c5d2 + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-flow": "npm:^7.23.3" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9ab627f9668fc1f95564b26bffd6706f86205960d9ccc168236752fbef65dbe10aa0ce74faae12f48bb3b72ec7f38ef2a78b4874c222c1e85754e981639f3b33 languageName: node linkType: hard -"@ethereum-waffle/ens@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/ens@npm:3.4.4" +"@babel/plugin-transform-for-of@npm:^7.0.0": + version: 7.23.6 + resolution: "@babel/plugin-transform-for-of@npm:7.23.6" dependencies: - "@ensdomains/ens": "npm:^0.4.4" - "@ensdomains/resolver": "npm:^0.2.4" - ethers: "npm:^5.5.2" - checksum: c419924fec2dde755ec0d4a1d0bf2d1317e46370d6b5dec6cc2f85636b31e00f53dc067196d0579be8802c3d0753310f591960b60e15c16968174d4553eece21 + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 46681b6ab10f3ca2d961f50d4096b62ab5d551e1adad84e64be1ee23e72eb2f26a1e30e617e853c74f1349fffe4af68d33921a128543b6f24b6d46c09a3e2aec languageName: node linkType: hard -"@ethereum-waffle/mock-contract@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/mock-contract@npm:3.4.4" +"@babel/plugin-transform-function-name@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-function-name@npm:7.23.3" dependencies: - "@ethersproject/abi": "npm:^5.5.0" - ethers: "npm:^5.5.2" - checksum: cc91dee6822a772fa7c3aec555225e1dde952b39f2c6f10a2d45f9c908d71ece7e531fd56813aad9a5f9a486b85586865fee30cd30d595311137c87eb931e87d + "@babel/helper-compilation-targets": "npm:^7.22.15" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 89cb9747802118048115cf92a8f310752f02030549b26f008904990cbdc86c3d4a68e07ca3b5c46de8a46ed4df2cb576ac222c74c56de67253d2a3ddc2956083 languageName: node linkType: hard -"@ethereum-waffle/provider@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/provider@npm:3.4.4" +"@babel/plugin-transform-literals@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-literals@npm:7.23.3" dependencies: - "@ethereum-waffle/ens": "npm:^3.4.4" - ethers: "npm:^5.5.2" - ganache-core: "npm:^2.13.2" - patch-package: "npm:^6.2.2" - postinstall-postinstall: "npm:^2.1.0" - checksum: fb0ccd2a08e8d4af81a7ba20d6c3bc89ad9c70888495a851cfe4c5432c561b87199ab1d6647e2200c35502d1c55b86797eca760536ea5503606d2de4af2e76ed + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8292106b106201464c2bfdd5c014fe6a9ca1c0256eb0a8031deb20081e21906fe68b156186f77d993c23eeab6d8d6f5f66e8895eec7ed97ce6de5dbcafbcd7f4 languageName: node linkType: hard -"@ethereumjs/common@npm:2.5.0": - version: 2.5.0 - resolution: "@ethereumjs/common@npm:2.5.0" +"@babel/plugin-transform-member-expression-literals@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-member-expression-literals@npm:7.23.3" dependencies: - crc-32: "npm:^1.2.0" - ethereumjs-util: "npm:^7.1.1" - checksum: 98a11931150ccc4d204f3c5328979cac9928cbc0f73344427dc41561287f100670db8b0296ede04542b598a58a699f4709867fb652a17ab076bab0ef14185816 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 687f24f3ec60b627fef6e87b9e2770df77f76727b9d5f54fa4c84a495bb24eb4a20f1a6240fa22d339d45aac5eaeb1b39882e941bfd00cf498f9c53478d1ec88 languageName: node linkType: hard -"@ethereumjs/common@npm:^2.5.0, @ethereumjs/common@npm:^2.6.4": - version: 2.6.5 - resolution: "@ethereumjs/common@npm:2.6.5" +"@babel/plugin-transform-modules-commonjs@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" dependencies: - crc-32: "npm:^1.2.0" - ethereumjs-util: "npm:^7.1.5" - checksum: 065fc993e390631753e9cbc63987954338c42192d227e15a40d9a074eda9e9597916dca51970b59230c7d3b1294c5956258fe6ea29000b5555bf24fe3ff522c5 + "@babel/helper-module-transforms": "npm:^7.23.3" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-simple-access": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 5c8840c5c9ecba39367ae17c973ed13dbc43234147b77ae780eec65010e2a9993c5d717721b23e8179f7cf49decdd325c509b241d69cfbf92aa647a1d8d5a37d languageName: node linkType: hard -"@ethereumjs/rlp@npm:^4.0.1": - version: 4.0.1 - resolution: "@ethereumjs/rlp@npm:4.0.1" - bin: - rlp: bin/rlp - checksum: 78379f288e9d88c584c2159c725c4a667a9742981d638bad760ed908263e0e36bdbd822c0a902003e0701195fd1cbde7adad621cd97fdfbf552c45e835ce022c +"@babel/plugin-transform-object-super@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-object-super@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-replace-supers": "npm:^7.22.20" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a6856fd8c0afbe5b3318c344d4d201d009f4051e2f6ff6237ff2660593e93c5997a58772b13d639077c3e29ced3440247b29c496cd77b13af1e7559a70009775 languageName: node linkType: hard -"@ethereumjs/tx@npm:3.3.2": - version: 3.3.2 - resolution: "@ethereumjs/tx@npm:3.3.2" +"@babel/plugin-transform-parameters@npm:^7.0.0, @babel/plugin-transform-parameters@npm:^7.20.7": + version: 7.23.3 + resolution: "@babel/plugin-transform-parameters@npm:7.23.3" dependencies: - "@ethereumjs/common": "npm:^2.5.0" - ethereumjs-util: "npm:^7.1.2" - checksum: 36b38bb56e54293cc86b02cd7146c0e653235c42a765fe704e0efd9aa96c363995c201585ede798e75f974d6d123b6f775845da2c56fbce71d9d099dc03dcb16 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a8d4cbe0f6ba68d158f5b4215c63004fc37a1fdc539036eb388a9792017c8496ea970a1932ccb929308f61e53dc56676ed01d8df6f42bc0a85c7fd5ba82482b7 languageName: node linkType: hard -"@ethereumjs/tx@npm:^3.3.2": - version: 3.5.2 - resolution: "@ethereumjs/tx@npm:3.5.2" +"@babel/plugin-transform-property-literals@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-property-literals@npm:7.23.3" dependencies: - "@ethereumjs/common": "npm:^2.6.4" - ethereumjs-util: "npm:^7.1.5" - checksum: 768cbe0834eef15f4726b44f2a4c52b6180884d90e58108d5251668c7e89d58572de7375d5e63be9d599e79c09259e643837a2afe876126b09c47ac35386cc20 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b2549f23f90cf276c2e3058c2225c3711c2ad1c417e336d3391199445a9776dd791b83be47b2b9a7ae374b40652d74b822387e31fa5267a37bf49c122e1a9747 languageName: node linkType: hard -"@ethereumjs/util@npm:^8.1.0": - version: 8.1.0 - resolution: "@ethereumjs/util@npm:8.1.0" +"@babel/plugin-transform-react-display-name@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-display-name@npm:7.23.3" dependencies: - "@ethereumjs/rlp": "npm:^4.0.1" - ethereum-cryptography: "npm:^2.0.0" - micro-ftch: "npm:^0.3.1" - checksum: 4e6e0449236f66b53782bab3b387108f0ddc050835bfe1381c67a7c038fea27cb85ab38851d98b700957022f0acb6e455ca0c634249cfcce1a116bad76500160 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3aed142af7bd1aed1df2bdad91ed33ba1cdd5c3c67ce6eafba821ff72f129162a197ffb55f1eb1775af276abd5545934489a8257fef6c6665ddf253a4f39a939 languageName: node linkType: hard -"@ethersproject/abi@npm:5.0.0-beta.153": - version: 5.0.0-beta.153 - resolution: "@ethersproject/abi@npm:5.0.0-beta.153" +"@babel/plugin-transform-react-jsx@npm:^7.0.0": + version: 7.23.4 + resolution: "@babel/plugin-transform-react-jsx@npm:7.23.4" dependencies: - "@ethersproject/address": "npm:>=5.0.0-beta.128" - "@ethersproject/bignumber": "npm:>=5.0.0-beta.130" - "@ethersproject/bytes": "npm:>=5.0.0-beta.129" - "@ethersproject/constants": "npm:>=5.0.0-beta.128" - "@ethersproject/hash": "npm:>=5.0.0-beta.128" - "@ethersproject/keccak256": "npm:>=5.0.0-beta.127" - "@ethersproject/logger": "npm:>=5.0.0-beta.129" - "@ethersproject/properties": "npm:>=5.0.0-beta.131" - "@ethersproject/strings": "npm:>=5.0.0-beta.130" - checksum: 56a6b04596f75f5ac11f68963f1a3bef628732fd9e5ccc6d5752b1c1bf8fb8cdfae02aeacf5087cd40cd52d76d63d936850af55cd984e862c6998410031bef54 + "@babel/helper-annotate-as-pure": "npm:^7.22.5" + "@babel/helper-module-imports": "npm:^7.22.15" + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/plugin-syntax-jsx": "npm:^7.23.3" + "@babel/types": "npm:^7.23.4" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8851b3adc515cd91bdb06ff3a23a0f81f0069cfef79dfb3fa744da4b7a82e3555ccb6324c4fa71ecf22508db13b9ff6a0ed96675f95fc87903b9fc6afb699580 languageName: node linkType: hard -"@ethersproject/abi@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/abi@npm:5.6.0" +"@babel/plugin-transform-shorthand-properties@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.23.3" dependencies: - "@ethersproject/address": "npm:^5.6.0" - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" - "@ethersproject/hash": "npm:^5.6.0" - "@ethersproject/keccak256": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - checksum: 17bfdeade4fed887b64708b409c665a034a94fc0d409b6f95498f0f752dd27306e71f1de55ce231f3fc0034f4579943e572ef742673ec6e5d69c136cbe70d942 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c423c66fec0b6503f50561741754c84366ef9e9818442c8881fbaa90cc363fd137084b9431cdc00ed2f1fd8c8a1a5982c4a7e1f2af3769db4caf2ac7ea55d4f0 languageName: node linkType: hard -"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.5.0, @ethersproject/abi@npm:^5.6.0, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abi@npm:5.7.0" +"@babel/plugin-transform-spread@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-spread@npm:7.23.3" dependencies: - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: 7de51bf52ff03df2526546dacea6e74f15d4c5ef762d931552082b9600dcefd8e333599f02d7906ba89f7b7f48c45ab72cee76f397212b4f17fa9d9ff5615916 + "@babel/helper-plugin-utils": "npm:^7.22.5" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a348e4ae47e4ceeceb760506ec7bf835ccc18a2cf70ec74ebfbe41bc172fa2412b05b7d1b86836f8aee375e41a04ff20486074778d0e2d19d668b33dc52e9dbb languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/abstract-provider@npm:5.6.0" +"@babel/plugin-transform-template-literals@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-template-literals@npm:7.23.3" dependencies: - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/networks": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/transactions": "npm:^5.6.0" - "@ethersproject/web": "npm:^5.6.0" - checksum: d36fbf1f6098ef6b04a19567b8234620d19256ec77f2537d099c2b7afc666fd85c1bcdb955228fc213bfcd31e3a31e3016e1f824599a27521b81ccae22179e5b + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9b5f43788b9ffcb8f2b445a16b1aa40fcf23cb0446a4649445f098ec6b4cb751f243a535da623d59fefe48f4c40552f5621187a61811779076bab26863e3373d languageName: node linkType: hard -"@ethersproject/abstract-provider@npm:5.7.0, @ethersproject/abstract-provider@npm:^5.6.0, @ethersproject/abstract-provider@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abstract-provider@npm:5.7.0" +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.5.5": + version: 7.23.9 + resolution: "@babel/runtime@npm:7.23.9" dependencies: - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/networks": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - "@ethersproject/web": "npm:^5.7.0" - checksum: a5708e2811b90ddc53d9318ce152511a32dd4771aa2fb59dbe9e90468bb75ca6e695d958bf44d13da684dc3b6aab03f63d425ff7591332cb5d7ddaf68dff7224 + regenerator-runtime: "npm:^0.14.0" + checksum: e71205fdd7082b2656512cc98e647d9ea7e222e4fe5c36e9e5adc026446fcc3ba7b3cdff8b0b694a0b78bb85db83e7b1e3d4c56ef90726682b74f13249cf952d languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/abstract-signer@npm:5.6.0" +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/template@npm:7.23.9" dependencies: - "@ethersproject/abstract-provider": "npm:^5.6.0" - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - checksum: 8c84e7545fda6b7ebf2115700f5bdd6d41ba89a1547bc7fab51ce3ada4802d6ea84d5c87700c212d999ee6f8f374e8e123b1f67b08ff99dd77bd1defb633e042 + "@babel/code-frame": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: 0e8b60119433787742bc08ae762bbd8d6755611c4cabbcb7627b292ec901a55af65d93d1c88572326069efb64136ef151ec91ffb74b2df7689bbab237030833a languageName: node linkType: hard -"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.6.0, @ethersproject/abstract-signer@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/abstract-signer@npm:5.7.0" +"@babel/traverse@npm:^7.14.0, @babel/traverse@npm:^7.16.8, @babel/traverse@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/traverse@npm:7.23.9" dependencies: - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - checksum: e174966b3be17269a5974a3ae5eef6d15ac62ee8c300ceace26767f218f6bbf3de66f29d9a9c9ca300fa8551aab4c92e28d2cc772f5475fdeaa78d9b5be0e745 + "@babel/code-frame": "npm:^7.23.5" + "@babel/generator": "npm:^7.23.6" + "@babel/helper-environment-visitor": "npm:^7.22.20" + "@babel/helper-function-name": "npm:^7.23.0" + "@babel/helper-hoist-variables": "npm:^7.22.5" + "@babel/helper-split-export-declaration": "npm:^7.22.6" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + debug: "npm:^4.3.1" + globals: "npm:^11.1.0" + checksum: d1615d1d02f04d47111a7ea4446a1a6275668ca39082f31d51f08380de9502e19862be434eaa34b022ce9a17dbb8f9e2b73a746c654d9575f3a680a7ffdf5630 languageName: node linkType: hard -"@ethersproject/address@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/address@npm:5.6.0" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.16.8, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.23.4, @babel/types@npm:^7.23.6, @babel/types@npm:^7.23.9, @babel/types@npm:^7.8.3": + version: 7.23.9 + resolution: "@babel/types@npm:7.23.9" dependencies: - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/keccak256": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/rlp": "npm:^5.6.0" - checksum: dada2e1d800085ef97d380f84d7a929cfccc78856ead06c122045c2bfb896cd5affb47f01fb31af70cad56172135afc93679051267847d5896f3efcb2cbba216 + "@babel/helper-string-parser": "npm:^7.23.4" + "@babel/helper-validator-identifier": "npm:^7.22.20" + to-fast-properties: "npm:^2.0.0" + checksum: edc7bb180ce7e4d2aea10c6972fb10474341ac39ba8fdc4a27ffb328368dfdfbf40fca18e441bbe7c483774500d5c05e222cec276c242e952853dcaf4eb884f7 languageName: node linkType: hard -"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:>=5.0.0-beta.128, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.0.8, @ethersproject/address@npm:^5.6.0, @ethersproject/address@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/address@npm:5.7.0" - dependencies: - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/rlp": "npm:^5.7.0" - checksum: db5da50abeaae8f6cf17678323e8d01cad697f9a184b0593c62b71b0faa8d7e5c2ba14da78a998d691773ed6a8eb06701f65757218e0eaaeb134e5c5f3e5a908 +"@chainsafe/as-sha256@npm:^0.3.1": + version: 0.3.1 + resolution: "@chainsafe/as-sha256@npm:0.3.1" + checksum: 72561fc6552a53e4d1fc28880b7f82ecb7a997670568333cb479f323db9482a6a59dd9d0f915210703e51c3a4ca2701ccdb4c66a0202abab4872d81184c9212e languageName: node linkType: hard -"@ethersproject/base64@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/base64@npm:5.6.0" +"@chainsafe/persistent-merkle-tree@npm:^0.4.2": + version: 0.4.2 + resolution: "@chainsafe/persistent-merkle-tree@npm:0.4.2" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - checksum: 5aa21dfae72a59495823ad89251a56813dd63160d593aa126c2dfc4bd4d650318d81e4000eff6cd1eb8cfce2494300a1bf9a96e2688e2fba642e8bc5bc7a363e + "@chainsafe/as-sha256": "npm:^0.3.1" + checksum: 9533e478a1a990e8cf8710a2eeb84c6f08c7b61726a43dbe2165316256839c29a2ff17923bce5e5effec446d832de8b0a5bc896ef5db80bce059af5d1bd20d8d languageName: node linkType: hard -"@ethersproject/base64@npm:5.7.0, @ethersproject/base64@npm:^5.6.0, @ethersproject/base64@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/base64@npm:5.7.0" +"@chainsafe/persistent-merkle-tree@npm:^0.5.0": + version: 0.5.0 + resolution: "@chainsafe/persistent-merkle-tree@npm:0.5.0" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - checksum: 4f748cd82af60ff1866db699fbf2bf057feff774ea0a30d1f03ea26426f53293ea10cc8265cda1695301da61093bedb8cc0d38887f43ed9dad96b78f19d7337e + "@chainsafe/as-sha256": "npm:^0.3.1" + checksum: 73c7a7536f49aceab61870fcc1dafef8a8be2ae0bfff2614846bb4b57a21939da75bca7bc5d1959cd312a5133be0acaf0e30fb323410c57592e9ec384758efe0 languageName: node linkType: hard -"@ethersproject/basex@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/basex@npm:5.6.0" +"@chainsafe/ssz@npm:^0.10.0": + version: 0.10.2 + resolution: "@chainsafe/ssz@npm:0.10.2" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - checksum: db108a14a7a34e538d993c8fcd18444226f9c65af80672670c784ced56b8b8e07348176394525a2675971fb30406a035dc9a3038cd478d05099712b48ba6d87f + "@chainsafe/as-sha256": "npm:^0.3.1" + "@chainsafe/persistent-merkle-tree": "npm:^0.5.0" + checksum: be427eba9f9c4a542326f9f3c20eb704c1c2500c4f124ba18febf6ffd5bb7bd5755228d99326bf6c4e4d969daa4b6ff2efb743688ec36ef86f20c0c673c0e967 languageName: node linkType: hard -"@ethersproject/basex@npm:5.7.0, @ethersproject/basex@npm:^5.6.0, @ethersproject/basex@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/basex@npm:5.7.0" +"@chainsafe/ssz@npm:^0.9.2": + version: 0.9.4 + resolution: "@chainsafe/ssz@npm:0.9.4" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - checksum: 02304de77477506ad798eb5c68077efd2531624380d770ef4a823e631a288fb680107a0f9dc4a6339b2a0b0f5b06ee77f53429afdad8f950cde0f3e40d30167d + "@chainsafe/as-sha256": "npm:^0.3.1" + "@chainsafe/persistent-merkle-tree": "npm:^0.4.2" + case: "npm:^1.6.3" + checksum: 4ce4b867c60dbee98772fe075037c7ef9a7894f97a4fb04f3cfd57e11fa683b8c23a4d80b53592d10fbd4e2abac43c9099181cfaee587619366f49091b9e5fcb languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/bignumber@npm:5.6.0" - dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - bn.js: "npm:^4.11.9" - checksum: f8f76238d9e975a849a331f6569621bfb57c0ffb62a736e67fd129a1b1ea29c0542cb8c594fcc4fbb8cd12f2625a891ad87675aeb7f524ca7808818b884721d9 +"@changesets/apply-release-plan@npm:^7.0.0": + version: 7.0.0 + resolution: "@changesets/apply-release-plan@npm:7.0.0" + dependencies: + "@babel/runtime": "npm:^7.20.1" + "@changesets/config": "npm:^3.0.0" + "@changesets/get-version-range-type": "npm:^0.4.0" + "@changesets/git": "npm:^3.0.0" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + detect-indent: "npm:^6.0.0" + fs-extra: "npm:^7.0.1" + lodash.startcase: "npm:^4.4.0" + outdent: "npm:^0.5.0" + prettier: "npm:^2.7.1" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.5.3" + checksum: 5f4c2d6b500d0ade51b31bc03b2475dd0bcaf3a31995f2ad953a6c3b05d3fb588568470bad3093d052f351ecdc6f8e2124d38941210361692b81bf62afbba7d7 languageName: node linkType: hard -"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:>=5.0.0-beta.130, @ethersproject/bignumber@npm:^5.1.1, @ethersproject/bignumber@npm:^5.6.0, @ethersproject/bignumber@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/bignumber@npm:5.7.0" +"@changesets/assemble-release-plan@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/assemble-release-plan@npm:6.0.0" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - bn.js: "npm:^5.2.1" - checksum: 14263cdc91a7884b141d9300f018f76f69839c47e95718ef7161b11d2c7563163096fee69724c5fa8ef6f536d3e60f1c605819edbc478383a2b98abcde3d37b2 + "@babel/runtime": "npm:^7.20.1" + "@changesets/errors": "npm:^0.2.0" + "@changesets/get-dependents-graph": "npm:^2.0.0" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + semver: "npm:^7.5.3" + checksum: 7ccff4dba07fd5c7d219b69d6f5e5ec4ea942b3f3482a76be6f9caa072ae5b2128b4d6c561030cb488ca1bc23416a2f8f638daa784f4ae9792c89c9b571231b3 languageName: node linkType: hard -"@ethersproject/bytes@npm:5.6.1": - version: 5.6.1 - resolution: "@ethersproject/bytes@npm:5.6.1" - dependencies: - "@ethersproject/logger": "npm:^5.6.0" - checksum: 6bc6c8d7eebfe13b2976851920bf11e6b0dcc2ee91a8e013ca6ab9b55a4de7ccf9b3c8f4cdc777547c5ddc795a8ada0bf79ca91482e88d01e3957c901c0fef55 +"@changesets/changelog-git@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/changelog-git@npm:0.2.0" + dependencies: + "@changesets/types": "npm:^6.0.0" + checksum: d94df555656ac4ac9698d87a173b1955227ac0f1763d59b9b4d4f149ab3f879ca67603e48407b1dfdadaef4e7882ae7bbc7b7be160a45a55f05442004bdc61bd + languageName: node + linkType: hard + +"@changesets/cli@npm:^2.27.1": + version: 2.27.1 + resolution: "@changesets/cli@npm:2.27.1" + dependencies: + "@babel/runtime": "npm:^7.20.1" + "@changesets/apply-release-plan": "npm:^7.0.0" + "@changesets/assemble-release-plan": "npm:^6.0.0" + "@changesets/changelog-git": "npm:^0.2.0" + "@changesets/config": "npm:^3.0.0" + "@changesets/errors": "npm:^0.2.0" + "@changesets/get-dependents-graph": "npm:^2.0.0" + "@changesets/get-release-plan": "npm:^4.0.0" + "@changesets/git": "npm:^3.0.0" + "@changesets/logger": "npm:^0.1.0" + "@changesets/pre": "npm:^2.0.0" + "@changesets/read": "npm:^0.6.0" + "@changesets/types": "npm:^6.0.0" + "@changesets/write": "npm:^0.3.0" + "@manypkg/get-packages": "npm:^1.1.3" + "@types/semver": "npm:^7.5.0" + ansi-colors: "npm:^4.1.3" + chalk: "npm:^2.1.0" + ci-info: "npm:^3.7.0" + enquirer: "npm:^2.3.0" + external-editor: "npm:^3.1.0" + fs-extra: "npm:^7.0.1" + human-id: "npm:^1.0.2" + meow: "npm:^6.0.0" + outdent: "npm:^0.5.0" + p-limit: "npm:^2.2.0" + preferred-pm: "npm:^3.0.0" + resolve-from: "npm:^5.0.0" + semver: "npm:^7.5.3" + spawndamnit: "npm:^2.0.0" + term-size: "npm:^2.1.0" + tty-table: "npm:^4.1.5" + bin: + changeset: bin.js + checksum: c7adc35f22983be9b0f6a8e4c3bc7013208ddf341b637530b88267e78469f0b7af9e36b138bea9f2fe29bb7b44294cd08aa0301a5cba0c6a928824f11d024e04 languageName: node linkType: hard -"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:>=5.0.0-beta.129, @ethersproject/bytes@npm:^5.0.8, @ethersproject/bytes@npm:^5.6.0, @ethersproject/bytes@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/bytes@npm:5.7.0" +"@changesets/config@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/config@npm:3.0.0" dependencies: - "@ethersproject/logger": "npm:^5.7.0" - checksum: 07dd1f0341b3de584ef26c8696674ff2bb032f4e99073856fc9cd7b4c54d1d846cabe149e864be267934658c3ce799e5ea26babe01f83af0e1f06c51e5ac791f + "@changesets/errors": "npm:^0.2.0" + "@changesets/get-dependents-graph": "npm:^2.0.0" + "@changesets/logger": "npm:^0.1.0" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + fs-extra: "npm:^7.0.1" + micromatch: "npm:^4.0.2" + checksum: c64463a92b99986e42657c3b8804851aab8b592bb64532177ce35769a7fedfad3ce1395ad0e2ab3e357e3029fd23333bff1ce51bc3634e6f43223724398639d3 languageName: node linkType: hard -"@ethersproject/constants@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/constants@npm:5.6.0" +"@changesets/errors@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/errors@npm:0.2.0" dependencies: - "@ethersproject/bignumber": "npm:^5.6.0" - checksum: 61c8b0ceab8a3bdf10b15bd32c16343ea3149ddafaedb6698fb7fcf850e29061323cb3fcf93a00c79f33ba481f3e5e2547e1dc63ace9fe46fcdb48bf69e8d31b + extendable-error: "npm:^0.1.5" + checksum: f2757c752ab04e9733b0dfd7903f1caf873f9e603794c4d9ea2294af4f937c73d07273c24be864ad0c30b6a98424360d5b96a6eab14f97f3cf2cbfd3763b95c1 languageName: node linkType: hard -"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:>=5.0.0-beta.128, @ethersproject/constants@npm:^5.6.0, @ethersproject/constants@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/constants@npm:5.7.0" +"@changesets/get-dependents-graph@npm:^2.0.0": + version: 2.0.0 + resolution: "@changesets/get-dependents-graph@npm:2.0.0" dependencies: - "@ethersproject/bignumber": "npm:^5.7.0" - checksum: 6df63ab753e152726b84595250ea722165a5744c046e317df40a6401f38556385a37c84dadf5b11ca651c4fb60f967046125369c57ac84829f6b30e69a096273 + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + chalk: "npm:^2.1.0" + fs-extra: "npm:^7.0.1" + semver: "npm:^7.5.3" + checksum: 68ac8f7f0b7b6f671b9809541238798aebe9250b083f6d9dace1305c436b565a71634412e83f642c6b21ed8656f4d548c92f583d2f4c6bf7a8665f6dddf14309 languageName: node linkType: hard -"@ethersproject/contracts@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/contracts@npm:5.6.0" +"@changesets/get-release-plan@npm:^4.0.0": + version: 4.0.0 + resolution: "@changesets/get-release-plan@npm:4.0.0" dependencies: - "@ethersproject/abi": "npm:^5.6.0" - "@ethersproject/abstract-provider": "npm:^5.6.0" - "@ethersproject/abstract-signer": "npm:^5.6.0" - "@ethersproject/address": "npm:^5.6.0" - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/transactions": "npm:^5.6.0" - checksum: 1a97c93acef2125cf68b1cd0bdc950188f5231e68216dcce2a81624f438713c1364c994ac600e549491bd889599e948fe96adae5bf6244667cba9d2ba1c83323 + "@babel/runtime": "npm:^7.20.1" + "@changesets/assemble-release-plan": "npm:^6.0.0" + "@changesets/config": "npm:^3.0.0" + "@changesets/pre": "npm:^2.0.0" + "@changesets/read": "npm:^0.6.0" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + checksum: d77140ca1d45a6e70c3ed8a3859986a7d1ae40c015a8ca85910acec6455e333311c78e3664d9cee02ed540020f7bacde1846d3cff58ec2ffd64edd55bf8a114b languageName: node linkType: hard -"@ethersproject/contracts@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/contracts@npm:5.7.0" - dependencies: - "@ethersproject/abi": "npm:^5.7.0" - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - checksum: 97a10361dddaccfb3e9e20e24d071cfa570050adcb964d3452c5f7c9eaaddb4e145ec9cf928e14417948701b89e81d4907800e799a6083123e4d13a576842f41 +"@changesets/get-version-range-type@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/get-version-range-type@npm:0.4.0" + checksum: e466208c8383489a383f37958d8b5b9aed38539f9287b47fe155a2e8855973f6960fb1724a1ee33b11580d65e1011059045ee654e8ef51e4783017d8989c9d3f languageName: node linkType: hard -"@ethersproject/experimental@npm:^5.6.0, @ethersproject/experimental@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/experimental@npm:5.7.0" +"@changesets/git@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/git@npm:3.0.0" dependencies: - "@ethersproject/web": "npm:^5.7.0" - ethers: "npm:^5.7.0" - scrypt-js: "npm:3.0.1" - checksum: 0546f8737ca062ce7d4a890d9cb354fde34b10b042b1d6b26e7206810c39d0fdb7ac20e60686a89f3f41faf33cc4c4c7366f49700a2d0978f0457e79759a79a4 + "@babel/runtime": "npm:^7.20.1" + "@changesets/errors": "npm:^0.2.0" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + is-subdir: "npm:^1.1.1" + micromatch: "npm:^4.0.2" + spawndamnit: "npm:^2.0.0" + checksum: 75b0ce2d8c52c8141a2d07be1cc05da15463d6f93a8a95351e171c6c3d48345b3134f33bfeb695a11467adbcc51ff3d87487995a61fba99af89063eac4a8ce7a languageName: node linkType: hard -"@ethersproject/hash@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/hash@npm:5.6.0" +"@changesets/logger@npm:^0.1.0": + version: 0.1.0 + resolution: "@changesets/logger@npm:0.1.0" dependencies: - "@ethersproject/abstract-signer": "npm:^5.6.0" - "@ethersproject/address": "npm:^5.6.0" - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/keccak256": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - checksum: dd7dae9576dcaff1255ab2a65514e2c5f59a6a66efddc4144dc68d8f45c6bd26fdd8ed528f2cd949082526b64e2d5d8d786b9646812d310af911affc878199b4 + chalk: "npm:^2.1.0" + checksum: b40365a4e62be4bf7a75c5900e8f95b1abd8fb9ff9f2cf71a7b567532377ddd5490b0ee1d566189a91e8c8250c9e875d333cfb3e44a34c230a11fd61337f923e languageName: node linkType: hard -"@ethersproject/hash@npm:5.7.0, @ethersproject/hash@npm:>=5.0.0-beta.128, @ethersproject/hash@npm:^5.6.0, @ethersproject/hash@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/hash@npm:5.7.0" +"@changesets/parse@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/parse@npm:0.4.0" dependencies: - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/base64": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: 1a631dae34c4cf340dde21d6940dd1715fc7ae483d576f7b8ef9e8cb1d0e30bd7e8d30d4a7d8dc531c14164602323af2c3d51eb2204af18b2e15167e70c9a5ef + "@changesets/types": "npm:^6.0.0" + js-yaml: "npm:^3.13.1" + checksum: 8e76f8540aceb2263eb76c97f027c1990fc069bf275321ad0aabf843cb51bc6711b13118eda35c701a30a36d26f48e75f7afc14e9a5c863f8a98091021fd5d61 languageName: node linkType: hard -"@ethersproject/hdnode@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/hdnode@npm:5.6.0" +"@changesets/pre@npm:^2.0.0": + version: 2.0.0 + resolution: "@changesets/pre@npm:2.0.0" dependencies: - "@ethersproject/abstract-signer": "npm:^5.6.0" - "@ethersproject/basex": "npm:^5.6.0" - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/pbkdf2": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/sha2": "npm:^5.6.0" - "@ethersproject/signing-key": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - "@ethersproject/transactions": "npm:^5.6.0" - "@ethersproject/wordlists": "npm:^5.6.0" - checksum: 59f19629a8071366dcffae903f32ad8675640a9027541912e880bc225ed61736ebd20f774e44a586e37d79c122cffed42b3e9ec4c35db78d1d025d2e14a060ba + "@babel/runtime": "npm:^7.20.1" + "@changesets/errors": "npm:^0.2.0" + "@changesets/types": "npm:^6.0.0" + "@manypkg/get-packages": "npm:^1.1.3" + fs-extra: "npm:^7.0.1" + checksum: 3971fb9b3f8b1719a983b82fcd34aab573151d0765ff38ae44f31d66d040ca40d33e80808b3694ae40331ebf6d654d479352c3bc0a964ad553200ebf5d1ec44f languageName: node linkType: hard -"@ethersproject/hdnode@npm:5.7.0, @ethersproject/hdnode@npm:^5.6.0, @ethersproject/hdnode@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/hdnode@npm:5.7.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/basex": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/pbkdf2": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - "@ethersproject/signing-key": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - "@ethersproject/wordlists": "npm:^5.7.0" - checksum: 36d5c13fe69b1e0a18ea98537bc560d8ba166e012d63faac92522a0b5f405eb67d8848c5aca69e2470f62743aaef2ac36638d9e27fd8c68f51506eb61479d51d +"@changesets/read@npm:^0.6.0": + version: 0.6.0 + resolution: "@changesets/read@npm:0.6.0" + dependencies: + "@babel/runtime": "npm:^7.20.1" + "@changesets/git": "npm:^3.0.0" + "@changesets/logger": "npm:^0.1.0" + "@changesets/parse": "npm:^0.4.0" + "@changesets/types": "npm:^6.0.0" + chalk: "npm:^2.1.0" + fs-extra: "npm:^7.0.1" + p-filter: "npm:^2.1.0" + checksum: ec2914fb89de923145a3482e00a2930b011c9c7a7c5690b053e344e8e8941ab06087bd3fe3b6cc01a651656c0438b5f9b96c616c7df1ad146f87b8751701bf5a languageName: node linkType: hard -"@ethersproject/json-wallets@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/json-wallets@npm:5.6.0" - dependencies: - "@ethersproject/abstract-signer": "npm:^5.6.0" - "@ethersproject/address": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/hdnode": "npm:^5.6.0" - "@ethersproject/keccak256": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/pbkdf2": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/random": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - "@ethersproject/transactions": "npm:^5.6.0" - aes-js: "npm:3.0.0" - scrypt-js: "npm:3.0.1" - checksum: 0753e152f892a06736f3c0a8d837005a393b566a6b146d818375b32377f526ee4c79d854e8168e586cf32242a640f1b10b460278fcb8eb7e1fcd5ecda1f1a974 +"@changesets/types@npm:^4.0.1": + version: 4.1.0 + resolution: "@changesets/types@npm:4.1.0" + checksum: a372ad21f6a1e0d4ce6c19573c1ca269eef1ad53c26751ad9515a24f003e7c49dcd859dbb1fedb6badaf7be956c1559e8798304039e0ec0da2d9a68583f13464 languageName: node linkType: hard -"@ethersproject/json-wallets@npm:5.7.0, @ethersproject/json-wallets@npm:^5.6.0, @ethersproject/json-wallets@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/json-wallets@npm:5.7.0" +"@changesets/types@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/types@npm:6.0.0" + checksum: e755f208792547e3b9ece15ce4da22466267da810c6fd87d927a1b8cec4d7fb7f0eea0d1a7585747676238e3e4ba1ffdabe016ccb05cfa537b4e4b03ec399f41 + languageName: node + linkType: hard + +"@changesets/write@npm:^0.3.0": + version: 0.3.0 + resolution: "@changesets/write@npm:0.3.0" dependencies: - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/hdnode": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/pbkdf2": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/random": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - aes-js: "npm:3.0.0" - scrypt-js: "npm:3.0.1" - checksum: f1a84d19ff38d3506f453abc4702107cbc96a43c000efcd273a056371363767a06a8d746f84263b1300266eb0c329fe3b49a9b39a37aadd016433faf9e15a4bb + "@babel/runtime": "npm:^7.20.1" + "@changesets/types": "npm:^6.0.0" + fs-extra: "npm:^7.0.1" + human-id: "npm:^1.0.2" + prettier: "npm:^2.7.1" + checksum: 537f419d854946cce5694696b6a48ffee0ea1f7b5c97c5246836931886db18153c42a7dea1e74b0e8bf571fcded527e2f443ab362fdb1e4129bd95a61b2d0fe5 languageName: node linkType: hard -"@ethersproject/keccak256@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/keccak256@npm:5.6.0" +"@colors/colors@npm:1.5.0": + version: 1.5.0 + resolution: "@colors/colors@npm:1.5.0" + checksum: eb42729851adca56d19a08e48d5a1e95efd2a32c55ae0323de8119052be0510d4b7a1611f2abcbf28c044a6c11e6b7d38f99fccdad7429300c37a8ea5fb95b44 + languageName: node + linkType: hard + +"@colors/colors@npm:1.6.0, @colors/colors@npm:^1.6.0": + version: 1.6.0 + resolution: "@colors/colors@npm:1.6.0" + checksum: 9328a0778a5b0db243af54455b79a69e3fb21122d6c15ef9e9fcc94881d8d17352d8b2b2590f9bdd46fac5c2d6c1636dcfc14358a20c70e22daf89e1a759b629 + languageName: node + linkType: hard + +"@commitlint/cli@npm:^18.4.3": + version: 18.6.1 + resolution: "@commitlint/cli@npm:18.6.1" + dependencies: + "@commitlint/format": "npm:^18.6.1" + "@commitlint/lint": "npm:^18.6.1" + "@commitlint/load": "npm:^18.6.1" + "@commitlint/read": "npm:^18.6.1" + "@commitlint/types": "npm:^18.6.1" + execa: "npm:^5.0.0" + lodash.isfunction: "npm:^3.0.9" + resolve-from: "npm:5.0.0" + resolve-global: "npm:1.0.0" + yargs: "npm:^17.0.0" + bin: + commitlint: cli.js + checksum: 4ec3eec2919170aece1295253c70656d48b8f0fcb2a1f2e48819b1913effa1e92a2416a422f1cfa4b90c4b33b7a8b07184b40851bc906ac6b027b11a8927de50 + languageName: node + linkType: hard + +"@commitlint/config-conventional@npm:^18.4.3": + version: 18.6.2 + resolution: "@commitlint/config-conventional@npm:18.6.2" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - js-sha3: "npm:0.8.0" - checksum: 3f99e3bd7b1125bad4c1ac10c133c2e09b93d7675bc9a54e4b0f608520ebf20df36f6d83dd6804f2cbea3b51ffd800cc9532f7239c5e0803aa58d62d7f0d0d94 + "@commitlint/types": "npm:^18.6.1" + conventional-changelog-conventionalcommits: "npm:^7.0.2" + checksum: ff4ccff3c2992c209703eb7d08f8e1c6d8471d4f0778f384dc0fef490cc023227f1b662f7136a301804d650518e00c7f859aa3eb1a156448f837b2a50206430d languageName: node linkType: hard -"@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:>=5.0.0-beta.127, @ethersproject/keccak256@npm:^5.6.0, @ethersproject/keccak256@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/keccak256@npm:5.7.0" +"@commitlint/config-validator@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/config-validator@npm:18.6.1" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - js-sha3: "npm:0.8.0" - checksum: 3b1a91706ff11f5ab5496840b9c36cedca27db443186d28b94847149fd16baecdc13f6fc5efb8359506392f2aba559d07e7f9c1e17a63f9d5de9f8053cfcb033 + "@commitlint/types": "npm:^18.6.1" + ajv: "npm:^8.11.0" + checksum: 611dec17774e261189b041db180068c7951f6d85d12895497b5fe2408f77eccba32f8cec2bb656a165e99c2b038e806aa2d42e59e68eb0e090eb98b5b3f4e854 languageName: node linkType: hard -"@ethersproject/logger@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/logger@npm:5.6.0" - checksum: f4c2610cf25d833cc1bc0a4ce99227c30508f15c8acb423e8a15f12ac25e37f9f86779485e6f79a887b24df831bdbee949249eb5feb75c6b45ca761161739516 +"@commitlint/ensure@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/ensure@npm:18.6.1" + dependencies: + "@commitlint/types": "npm:^18.6.1" + lodash.camelcase: "npm:^4.3.0" + lodash.kebabcase: "npm:^4.1.1" + lodash.snakecase: "npm:^4.1.1" + lodash.startcase: "npm:^4.4.0" + lodash.upperfirst: "npm:^4.3.1" + checksum: b7fbc70dbf1c3010f47ab76b1115c28be24b11fe0d01d47e2d64666dee801c8e98961076777f10116c3cbfeed676979d702c98934c342feafc4cdce2ef48f62c languageName: node linkType: hard -"@ethersproject/logger@npm:5.7.0, @ethersproject/logger@npm:>=5.0.0-beta.129, @ethersproject/logger@npm:^5.6.0, @ethersproject/logger@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/logger@npm:5.7.0" - checksum: d03d460fb2d4a5e71c627b7986fb9e50e1b59a6f55e8b42a545b8b92398b961e7fd294bd9c3d8f92b35d0f6ff9d15aa14c95eab378f8ea194e943c8ace343501 +"@commitlint/execute-rule@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/execute-rule@npm:18.6.1" + checksum: cdbf397f533ddaf2d90e457d7917ad16e6d8b78fdc79aff583618c42c758159eaaec33bd92e7f5dfefd0d5c6652c5d36d511b5e73cf5a2de12eb018b1e6be5f0 languageName: node linkType: hard -"@ethersproject/networks@npm:5.6.1": - version: 5.6.1 - resolution: "@ethersproject/networks@npm:5.6.1" +"@commitlint/format@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/format@npm:18.6.1" dependencies: - "@ethersproject/logger": "npm:^5.6.0" - checksum: 3628b2a302dedbcb0c8c36f3e42faa688fdb46c7afe28ce95d02d2a5306a865b2f6c2e72ce6f701c3d15291d09e626d22910c10f39ea9016997ec1977d16a310 + "@commitlint/types": "npm:^18.6.1" + chalk: "npm:^4.1.0" + checksum: b72d6d75e34e32c7e1db8e46ff4cf27ba0880d7a72d6371a32faa5461a7f993dd14f006a5c6d66e6d0ccb571339fbaa96aa679d7ce332cdf81e2b4762b714ea2 languageName: node linkType: hard -"@ethersproject/networks@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/networks@npm:5.7.0" +"@commitlint/is-ignored@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/is-ignored@npm:18.6.1" dependencies: - "@ethersproject/logger": "npm:^5.7.0" - checksum: ac9f921a196bc8f7816c1ba43262bb22701f00ab599f4af8bd7275a7728b748ff428dd3445d375f7b2abdfe29bf85eff77cf132d25df8c78ff504c6b86c56e6e + "@commitlint/types": "npm:^18.6.1" + semver: "npm:7.6.0" + checksum: 9be99142a2e24db8fa67776351d2ab5d4e0ead013a3317e6e011eaf24a030605c312b8fb404092c38563823a21abf213294bf322bf42a0b60ddaaa4fd791e78c languageName: node linkType: hard -"@ethersproject/networks@npm:5.7.1, @ethersproject/networks@npm:^5.6.0, @ethersproject/networks@npm:^5.7.0": - version: 5.7.1 - resolution: "@ethersproject/networks@npm:5.7.1" +"@commitlint/lint@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/lint@npm:18.6.1" dependencies: - "@ethersproject/logger": "npm:^5.7.0" - checksum: 9efcdce27f150459e85d74af3f72d5c32898823a99f5410e26bf26cca2d21fb14e403377314a93aea248e57fb2964e19cee2c3f7bfc586ceba4c803a8f1b75c0 + "@commitlint/is-ignored": "npm:^18.6.1" + "@commitlint/parse": "npm:^18.6.1" + "@commitlint/rules": "npm:^18.6.1" + "@commitlint/types": "npm:^18.6.1" + checksum: a1e1648ee04875c0fdc82adbdcded89cbc645649d817ba069b3b0144ff74090d6ac43c2cf86e46615d1268c33cad7019d967ca769fc7c1e4ebd193b1c2363ee6 languageName: node linkType: hard -"@ethersproject/pbkdf2@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/pbkdf2@npm:5.6.0" +"@commitlint/load@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/load@npm:18.6.1" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/sha2": "npm:^5.6.0" - checksum: 5dbf03cb20dcd794db08dec21fc2a56feed7d13cf78d2358933ff936d6499b7d3c0169d0fde33cc0bfee31186df0db1dc732fd881499f3274964115be8140dfd + "@commitlint/config-validator": "npm:^18.6.1" + "@commitlint/execute-rule": "npm:^18.6.1" + "@commitlint/resolve-extends": "npm:^18.6.1" + "@commitlint/types": "npm:^18.6.1" + chalk: "npm:^4.1.0" + cosmiconfig: "npm:^8.3.6" + cosmiconfig-typescript-loader: "npm:^5.0.0" + lodash.isplainobject: "npm:^4.0.6" + lodash.merge: "npm:^4.6.2" + lodash.uniq: "npm:^4.5.0" + resolve-from: "npm:^5.0.0" + checksum: da4f90c92015016b97bff65b446011185b2701383929ba8f4a6e1307be919cb2c94e3b62906f460edded76c530f0185d13bee8fe20c4a78995bf8f6aae65ae30 languageName: node linkType: hard -"@ethersproject/pbkdf2@npm:5.7.0, @ethersproject/pbkdf2@npm:^5.6.0, @ethersproject/pbkdf2@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/pbkdf2@npm:5.7.0" - dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - checksum: e5a29cf28b4f4ca1def94d37cfb6a9c05c896106ed64881707813de01c1e7ded613f1e95febcccda4de96aae929068831d72b9d06beef1377b5a1a13a0eb3ff5 +"@commitlint/message@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/message@npm:18.6.1" + checksum: 46a81835961e474a924b219aee93754f80c8e1b3ad7e358667f831e67e8631612eed8227a0065486c32c10be8cacaa78f1dedb45e67aa2e31b677d11d1648cbd languageName: node linkType: hard -"@ethersproject/properties@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/properties@npm:5.6.0" +"@commitlint/parse@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/parse@npm:18.6.1" dependencies: - "@ethersproject/logger": "npm:^5.6.0" - checksum: a137e1002d1af1e37b81279df370081c5c0fab7492fedc9798a52c10c79c6c792fef30742bc8920570cf73bfff06d6f88e89b1ef68ebbb0360d1d8f1efa8fba9 + "@commitlint/types": "npm:^18.6.1" + conventional-changelog-angular: "npm:^7.0.0" + conventional-commits-parser: "npm:^5.0.0" + checksum: 286bf092436f73730ecd474737b4e53c3c268ade1f01c019a628c54654b3bf3387a151fcb0510dee49dd8d2e4b5ac6f69c62da2183198c0088ee67a06f8ad247 languageName: node linkType: hard -"@ethersproject/properties@npm:5.7.0, @ethersproject/properties@npm:>=5.0.0-beta.131, @ethersproject/properties@npm:^5.6.0, @ethersproject/properties@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/properties@npm:5.7.0" +"@commitlint/read@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/read@npm:18.6.1" dependencies: - "@ethersproject/logger": "npm:^5.7.0" - checksum: 4fe5d36e5550b8e23a305aa236a93e8f04d891d8198eecdc8273914c761b0e198fd6f757877406ee3eb05033ec271132a3e5998c7bd7b9a187964fb4f67b1373 + "@commitlint/top-level": "npm:^18.6.1" + "@commitlint/types": "npm:^18.6.1" + git-raw-commits: "npm:^2.0.11" + minimist: "npm:^1.2.6" + checksum: 92a88348b95ad058a6572484da5593f2471335a784965fed03bec36c786b99a467782aba231127d96c23f03a030d9aed17be197e5392a5f8636b818c3c2907ac languageName: node linkType: hard -"@ethersproject/providers@npm:5.6.2": - version: 5.6.2 - resolution: "@ethersproject/providers@npm:5.6.2" +"@commitlint/resolve-extends@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/resolve-extends@npm:18.6.1" dependencies: - "@ethersproject/abstract-provider": "npm:^5.6.0" - "@ethersproject/abstract-signer": "npm:^5.6.0" - "@ethersproject/address": "npm:^5.6.0" - "@ethersproject/basex": "npm:^5.6.0" - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" - "@ethersproject/hash": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/networks": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/random": "npm:^5.6.0" - "@ethersproject/rlp": "npm:^5.6.0" - "@ethersproject/sha2": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - "@ethersproject/transactions": "npm:^5.6.0" - "@ethersproject/web": "npm:^5.6.0" - bech32: "npm:1.1.4" - ws: "npm:7.4.6" - checksum: 9dc8c5ff0227cc7e377e7dac42f3191b9ff4430921069025beb531d0640b93d139ae4499f098711fd3212ad77ec6c0c403780c993fd2101e05ff40e2e9cf24a4 + "@commitlint/config-validator": "npm:^18.6.1" + "@commitlint/types": "npm:^18.6.1" + import-fresh: "npm:^3.0.0" + lodash.mergewith: "npm:^4.6.2" + resolve-from: "npm:^5.0.0" + resolve-global: "npm:^1.0.0" + checksum: 05fbf6742c2b3e719d40c112d37efd3b395aa17daeb1d23913f6a72f1cc2ec3c5ec7f3ba683eef12fe698c7002aa186b05c2fe0d0cefe16ef8e967d10d7c1397 languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/providers@npm:5.7.0" +"@commitlint/rules@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/rules@npm:18.6.1" dependencies: - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/base64": "npm:^5.7.0" - "@ethersproject/basex": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/networks": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/random": "npm:^5.7.0" - "@ethersproject/rlp": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - "@ethersproject/web": "npm:^5.7.0" - bech32: "npm:1.1.4" - ws: "npm:7.4.6" - checksum: 6da22fc08ee84d4f4ca806ab86d8ea17e031a820767c44190136a5210fb8962ea0531f06eeec5da0ab2d06eef815234be2f98ec017b1d3cac4c7fc511dfb5b4b + "@commitlint/ensure": "npm:^18.6.1" + "@commitlint/message": "npm:^18.6.1" + "@commitlint/to-lines": "npm:^18.6.1" + "@commitlint/types": "npm:^18.6.1" + execa: "npm:^5.0.0" + checksum: 6ba0a70295a3bc46304c4ca4212755751c774dc0e16aea25552e632495a585d595993c308e73710bba14d6908dd72de0a5a267f3604710c61746d6c3c7397c83 languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": - version: 5.7.2 - resolution: "@ethersproject/providers@npm:5.7.2" - dependencies: - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/base64": "npm:^5.7.0" - "@ethersproject/basex": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/networks": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/random": "npm:^5.7.0" - "@ethersproject/rlp": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - "@ethersproject/web": "npm:^5.7.0" - bech32: "npm:1.1.4" - ws: "npm:7.4.6" - checksum: 4c8d19e6b31f769c24042fb2d02e483a4ee60dcbfca9e3291f0a029b24337c47d1ea719a390be856f8fd02997125819e834415e77da4fb2023369712348dae4c +"@commitlint/to-lines@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/to-lines@npm:18.6.1" + checksum: 93c23ed056fb657618ac77b671d40fd6a90c5ecc3e850adb1715b4e4072b7a41575877e890d4c017c9f215f753ee2fd1189914fc2374d5383a4af4c5123a9f57 languageName: node linkType: hard -"@ethersproject/random@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/random@npm:5.6.0" +"@commitlint/top-level@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/top-level@npm:18.6.1" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - checksum: 85f56fcd572f158a9cbc7ca27d4f139bdb6073b1a5859940cbb6d11ffdb5d9a8b7adf812d726e590947ec2eb99ed7b86c06fcef081e0edb8ed7b7753ee84a02c + find-up: "npm:^5.0.0" + checksum: b3fc8ae12267f9c98e19f254e5eed26861c8805937883266e64397d23ef957bbd5826e53fb9c23bde55e3ae73d2963450dfa99c75425d58fec3f151f8f650cbc languageName: node linkType: hard -"@ethersproject/random@npm:5.7.0, @ethersproject/random@npm:^5.6.0, @ethersproject/random@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/random@npm:5.7.0" +"@commitlint/types@npm:^18.6.1": + version: 18.6.1 + resolution: "@commitlint/types@npm:18.6.1" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - checksum: 23e572fc55372653c22062f6a153a68c2e2d3200db734cd0d39621fbfd0ca999585bed2d5682e3ac65d87a2893048375682e49d1473d9965631ff56d2808580b + chalk: "npm:^4.1.0" + checksum: 5728f5cb62bcaad5158dd8982ab5d44c1ea1aee9ac251026cd91b9a4795bb912505c904f75cbd3ae0d1bb7b4dd1e5d84990b76093230018166af8e111b658685 languageName: node linkType: hard -"@ethersproject/rlp@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/rlp@npm:5.6.0" +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - checksum: f6d505fb0af334332f5a098c6e3969646e91d17a85b68db4e26228dd3866ac439e693c35337c5153e1b9e25f54c1e6c608548062fd0e7b5e9dc30c9ba8c553bd + "@jridgewell/trace-mapping": "npm:0.3.9" + checksum: 05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 languageName: node linkType: hard -"@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.6.0, @ethersproject/rlp@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/rlp@npm:5.7.0" +"@dabh/diagnostics@npm:^2.0.2": + version: 2.0.3 + resolution: "@dabh/diagnostics@npm:2.0.3" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - checksum: bc863d21dcf7adf6a99ae75c41c4a3fb99698cfdcfc6d5d82021530f3d3551c6305bc7b6f0475ad6de6f69e91802b7e872bee48c0596d98969aefcf121c2a044 + colorspace: "npm:1.1.x" + enabled: "npm:2.0.x" + kuler: "npm:^2.0.0" + checksum: a5133df8492802465ed01f2f0a5784585241a1030c362d54a602ed1839816d6c93d71dde05cf2ddb4fd0796238c19774406bd62fa2564b637907b495f52425fe languageName: node linkType: hard -"@ethersproject/sha2@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/sha2@npm:5.6.0" +"@defi-wonderland/smock@npm:^2.0.7": + version: 2.3.5 + resolution: "@defi-wonderland/smock@npm:2.3.5" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - hash.js: "npm:1.1.7" - checksum: a56818968c89213146f57cadfc20949157dbb6643fb6d40f4a6cd7fb4b0433d5e679cc5b7b9e2efa5a7c20ae6e7f634ac8f7f560431f158aa94b05d621c3b1f8 + "@nomicfoundation/ethereumjs-evm": "npm:^1.0.0-rc.3" + "@nomicfoundation/ethereumjs-util": "npm:^8.0.0-rc.3" + "@nomicfoundation/ethereumjs-vm": "npm:^6.0.0-rc.3" + diff: "npm:^5.0.0" + lodash.isequal: "npm:^4.5.0" + lodash.isequalwith: "npm:^4.4.0" + rxjs: "npm:^7.2.0" + semver: "npm:^7.3.5" + peerDependencies: + "@ethersproject/abi": ^5 + "@ethersproject/abstract-provider": ^5 + "@ethersproject/abstract-signer": ^5 + "@nomiclabs/hardhat-ethers": ^2 + ethers: ^5 + hardhat: ^2 + checksum: c831563fe6607841d69f5936011398a492f760f52f9cb17626b2949ff3ef7668729acc4a3a944f739417b2d1b99bc6c83580f236189f27431224021c66ac1821 languageName: node linkType: hard -"@ethersproject/sha2@npm:5.7.0, @ethersproject/sha2@npm:^5.6.0, @ethersproject/sha2@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/sha2@npm:5.7.0" +"@ensdomains/ens@npm:^0.4.4": + version: 0.4.5 + resolution: "@ensdomains/ens@npm:0.4.5" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - hash.js: "npm:1.1.7" - checksum: 0e7f9ce6b1640817b921b9c6dd9dab8d5bf5a0ce7634d6a7d129b7366a576c2f90dcf4bcb15a0aa9310dde67028f3a44e4fcc2f26b565abcd2a0f465116ff3b1 + bluebird: "npm:^3.5.2" + eth-ens-namehash: "npm:^2.0.8" + solc: "npm:^0.4.20" + testrpc: "npm:0.0.1" + web3-utils: "npm:^1.0.0-beta.31" + checksum: 15a77b5db73550546e6684cb6f8105170c9c113e3dc128ee718eabd3c2b1d13fdeb5791fa79c7b149b5b83b6e00040b7320c27796b7970fae66e8d3e5cce6561 languageName: node linkType: hard -"@ethersproject/signing-key@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/signing-key@npm:5.6.0" - dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - bn.js: "npm:^4.11.9" - elliptic: "npm:6.5.4" - hash.js: "npm:1.1.7" - checksum: 23da06746809652486458dc91c7df9f10a1e96653a70df40f8b51330cb1dba26e7f0270212ba029ff70a90cde94c48ef9fd2bae5d24d442e00e0b3f9ace4fd10 +"@ensdomains/resolver@npm:^0.2.4": + version: 0.2.4 + resolution: "@ensdomains/resolver@npm:0.2.4" + checksum: 8bd21f82c3f122f56d7198cf671c08204cca2cb531fd5074fd558d625afa8a15828e92738bf80b9961575a92e4fe627208edd3f87a04c6a0fa47531c91ef0639 languageName: node linkType: hard -"@ethersproject/signing-key@npm:5.7.0, @ethersproject/signing-key@npm:^5.6.0, @ethersproject/signing-key@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/signing-key@npm:5.7.0" +"@envelop/core@npm:^3.0.4, @envelop/core@npm:^3.0.6": + version: 3.0.6 + resolution: "@envelop/core@npm:3.0.6" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - bn.js: "npm:^5.2.1" - elliptic: "npm:6.5.4" - hash.js: "npm:1.1.7" - checksum: fe2ca55bcdb6e370d81372191d4e04671234a2da872af20b03c34e6e26b97dc07c1ee67e91b673680fb13344c9d5d7eae52f1fa6117733a3d68652b778843e09 + "@envelop/types": "npm:3.0.2" + tslib: "npm:^2.5.0" + checksum: 8196e997f351b7d1630fc6cfb6aa0fb4257dd1769cde12da227418508f1be433ed94271b433c47b5ccd5079728b93cdb7326738afda76d49c791f3ed736d7fc5 languageName: node linkType: hard -"@ethersproject/solidity@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/solidity@npm:5.6.0" +"@envelop/extended-validation@npm:^2.0.6": + version: 2.0.6 + resolution: "@envelop/extended-validation@npm:2.0.6" dependencies: - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/keccak256": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/sha2": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - checksum: df4dbc47a88783312f783d30a7bde523e55a4007ee5918606cd0178b4ba569cee42b7e6b8f04b8b911b648bb6eda6a51b5fae6e56e0303d69d35bff725417061 + "@graphql-tools/utils": "npm:^8.8.0" + tslib: "npm:^2.5.0" + peerDependencies: + "@envelop/core": ^3.0.6 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 0d1cb0184dd876bcbc731a90641fe71089daf13b515d21eb6803871f95ea7cc077195d5b37a70dc65f2de659964c88fbaa849f5f92f603002e9c642416623631 languageName: node linkType: hard -"@ethersproject/solidity@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/solidity@npm:5.7.0" +"@envelop/types@npm:3.0.2": + version: 3.0.2 + resolution: "@envelop/types@npm:3.0.2" dependencies: - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: bedf9918911144b0ec352b8aa7fa44abf63f0b131629c625672794ee196ba7d3992b0e0d3741935ca176813da25b9bcbc81aec454652c63113bdc3a1706beac6 + tslib: "npm:^2.5.0" + checksum: 1e71237bdb0d65256136760227402306e9d5aec1306f9e437085de2a1a0d8ea007be9302e9e397f96fd455f65da33cb3fe5822757af680ade9cecf218ce42a7c languageName: node linkType: hard -"@ethersproject/strings@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/strings@npm:5.6.0" +"@envelop/validation-cache@npm:^5.1.2": + version: 5.1.3 + resolution: "@envelop/validation-cache@npm:5.1.3" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - checksum: bd0fea07ac99365b4da10654419415c88ad319d8229a9b0fbd26632ed9549fb033e6cd491c5504d437718173254247628d223ebcab6d29e3ab9046b66563fdba + hash-it: "npm:^6.0.0" + lru-cache: "npm:^6.0.0" + tslib: "npm:^2.5.0" + peerDependencies: + "@envelop/core": ^3.0.6 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 4833d4f9fb24a65d728b0aaf8e9892cb3638992dacd41b5fe5e834971d3cec4cb5f238e12dfb833ddb448b9582fbb9d6ad5386ce8654ad14c3780c6242d408d1 languageName: node linkType: hard -"@ethersproject/strings@npm:5.7.0, @ethersproject/strings@npm:>=5.0.0-beta.130, @ethersproject/strings@npm:^5.6.0, @ethersproject/strings@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/strings@npm:5.7.0" +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": + version: 4.4.0 + resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - checksum: 570d87040ccc7d94de9861f76fc2fba6c0b84c5d6104a99a5c60b8a2401df2e4f24bf9c30afa536163b10a564a109a96f02e6290b80e8f0c610426f56ad704d1 + eslint-visitor-keys: "npm:^3.3.0" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 7e559c4ce59cd3a06b1b5a517b593912e680a7f981ae7affab0d01d709e99cd5647019be8fafa38c350305bc32f1f7d42c7073edde2ab536c745e365f37b607e languageName: node linkType: hard -"@ethersproject/transactions@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/transactions@npm:5.6.0" - dependencies: - "@ethersproject/address": "npm:^5.6.0" - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" - "@ethersproject/keccak256": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/rlp": "npm:^5.6.0" - "@ethersproject/signing-key": "npm:^5.6.0" - checksum: 23eecd1d9892dd5decd1720fe52ca84c2dda1629834ae1c399582d230130c91aef5d839cc6e67ad2916fe2acfd83cebd5f9dd534e2a808b10cd3360b4032b588 +"@eslint-community/regexpp@npm:^4.5.1, @eslint-community/regexpp@npm:^4.6.1": + version: 4.10.0 + resolution: "@eslint-community/regexpp@npm:4.10.0" + checksum: c5f60ef1f1ea7649fa7af0e80a5a79f64b55a8a8fa5086de4727eb4c86c652aedee407a9c143b8995d2c0b2d75c1222bec9ba5d73dbfc1f314550554f0979ef4 languageName: node linkType: hard -"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.0.0-beta.135, @ethersproject/transactions@npm:^5.6.0, @ethersproject/transactions@npm:^5.6.2, @ethersproject/transactions@npm:^5.7.0": - version: 5.7.0 - resolution: "@ethersproject/transactions@npm:5.7.0" +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: - "@ethersproject/address": "npm:^5.7.0" - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/keccak256": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/rlp": "npm:^5.7.0" - "@ethersproject/signing-key": "npm:^5.7.0" - checksum: aa4d51379caab35b9c468ed1692a23ae47ce0de121890b4f7093c982ee57e30bd2df0c743faed0f44936d7e59c55fffd80479f2c28ec6777b8de06bfb638c239 + ajv: "npm:^6.12.4" + debug: "npm:^4.3.2" + espree: "npm:^9.6.0" + globals: "npm:^13.19.0" + ignore: "npm:^5.2.0" + import-fresh: "npm:^3.2.1" + js-yaml: "npm:^4.1.0" + minimatch: "npm:^3.1.2" + strip-json-comments: "npm:^3.1.1" + checksum: 32f67052b81768ae876c84569ffd562491ec5a5091b0c1e1ca1e0f3c24fb42f804952fdd0a137873bc64303ba368a71ba079a6f691cee25beee9722d94cc8573 languageName: node linkType: hard -"@ethersproject/units@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/units@npm:5.6.0" +"@eslint/js@npm:8.56.0": + version: 8.56.0 + resolution: "@eslint/js@npm:8.56.0" + checksum: 60b3a1cf240e2479cec9742424224465dc50e46d781da1b7f5ef240501b2d1202c225bd456207faac4b34a64f4765833345bc4ddffd00395e1db40fa8c426f5a + languageName: node + linkType: hard + +"@eslint/js@npm:8.57.0": + version: 8.57.0 + resolution: "@eslint/js@npm:8.57.0" + checksum: 9a518bb8625ba3350613903a6d8c622352ab0c6557a59fe6ff6178bf882bf57123f9d92aa826ee8ac3ee74b9c6203fe630e9ee00efb03d753962dcf65ee4bd94 + languageName: node + linkType: hard + +"@ethereum-waffle/chai@npm:^3.4.4": + version: 3.4.4 + resolution: "@ethereum-waffle/chai@npm:3.4.4" dependencies: - "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - checksum: cb92acc910e00030009de917d9a7cea72def0536aceaaa9132d3d9fcedf4b39c7645ffc3950e747763a01048bb16ccd34cb0f0d6916d4d6a209ea809180a76be + "@ethereum-waffle/provider": "npm:^3.4.4" + ethers: "npm:^5.5.2" + checksum: 69921adf1d2320e853f7d61b8ce2cf45cdba746666097dc59f7578b22374f821b245e88368c563f3fa58c32d14c981d6025342a90a3cbc005ef84afc87fee807 languageName: node linkType: hard -"@ethersproject/units@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/units@npm:5.7.0" +"@ethereum-waffle/compiler@npm:^3.4.4": + version: 3.4.4 + resolution: "@ethereum-waffle/compiler@npm:3.4.4" dependencies: - "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - checksum: 4da2fdefe2a506cc9f8b408b2c8638ab35b843ec413d52713143f08501a55ff67a808897f9a91874774fb526423a0821090ba294f93e8bf4933a57af9677ac5e + "@resolver-engine/imports": "npm:^0.3.3" + "@resolver-engine/imports-fs": "npm:^0.3.3" + "@typechain/ethers-v5": "npm:^2.0.0" + "@types/mkdirp": "npm:^0.5.2" + "@types/node-fetch": "npm:^2.5.5" + ethers: "npm:^5.0.1" + mkdirp: "npm:^0.5.1" + node-fetch: "npm:^2.6.1" + solc: "npm:^0.6.3" + ts-generator: "npm:^0.1.1" + typechain: "npm:^3.0.0" + checksum: ea54d5e0094fc74ac4ae70d4149f5ee939ff265315ea851615f169447b94aabacb56567e6477518e24758e767084aab8c4ec089ad9442a6a742c279f5883c5d2 languageName: node linkType: hard -"@ethersproject/wallet@npm:5.6.0": +"@ethereum-waffle/ens@npm:^3.4.4": + version: 3.4.4 + resolution: "@ethereum-waffle/ens@npm:3.4.4" + dependencies: + "@ensdomains/ens": "npm:^0.4.4" + "@ensdomains/resolver": "npm:^0.2.4" + ethers: "npm:^5.5.2" + checksum: c419924fec2dde755ec0d4a1d0bf2d1317e46370d6b5dec6cc2f85636b31e00f53dc067196d0579be8802c3d0753310f591960b60e15c16968174d4553eece21 + languageName: node + linkType: hard + +"@ethereum-waffle/mock-contract@npm:^3.4.4": + version: 3.4.4 + resolution: "@ethereum-waffle/mock-contract@npm:3.4.4" + dependencies: + "@ethersproject/abi": "npm:^5.5.0" + ethers: "npm:^5.5.2" + checksum: cc91dee6822a772fa7c3aec555225e1dde952b39f2c6f10a2d45f9c908d71ece7e531fd56813aad9a5f9a486b85586865fee30cd30d595311137c87eb931e87d + languageName: node + linkType: hard + +"@ethereum-waffle/provider@npm:^3.4.4": + version: 3.4.4 + resolution: "@ethereum-waffle/provider@npm:3.4.4" + dependencies: + "@ethereum-waffle/ens": "npm:^3.4.4" + ethers: "npm:^5.5.2" + ganache-core: "npm:^2.13.2" + patch-package: "npm:^6.2.2" + postinstall-postinstall: "npm:^2.1.0" + checksum: fb0ccd2a08e8d4af81a7ba20d6c3bc89ad9c70888495a851cfe4c5432c561b87199ab1d6647e2200c35502d1c55b86797eca760536ea5503606d2de4af2e76ed + languageName: node + linkType: hard + +"@ethereumjs/common@npm:2.5.0": + version: 2.5.0 + resolution: "@ethereumjs/common@npm:2.5.0" + dependencies: + crc-32: "npm:^1.2.0" + ethereumjs-util: "npm:^7.1.1" + checksum: 98a11931150ccc4d204f3c5328979cac9928cbc0f73344427dc41561287f100670db8b0296ede04542b598a58a699f4709867fb652a17ab076bab0ef14185816 + languageName: node + linkType: hard + +"@ethereumjs/common@npm:^2.5.0, @ethereumjs/common@npm:^2.6.4": + version: 2.6.5 + resolution: "@ethereumjs/common@npm:2.6.5" + dependencies: + crc-32: "npm:^1.2.0" + ethereumjs-util: "npm:^7.1.5" + checksum: 065fc993e390631753e9cbc63987954338c42192d227e15a40d9a074eda9e9597916dca51970b59230c7d3b1294c5956258fe6ea29000b5555bf24fe3ff522c5 + languageName: node + linkType: hard + +"@ethereumjs/rlp@npm:^4.0.1": + version: 4.0.1 + resolution: "@ethereumjs/rlp@npm:4.0.1" + bin: + rlp: bin/rlp + checksum: 78379f288e9d88c584c2159c725c4a667a9742981d638bad760ed908263e0e36bdbd822c0a902003e0701195fd1cbde7adad621cd97fdfbf552c45e835ce022c + languageName: node + linkType: hard + +"@ethereumjs/tx@npm:3.3.2": + version: 3.3.2 + resolution: "@ethereumjs/tx@npm:3.3.2" + dependencies: + "@ethereumjs/common": "npm:^2.5.0" + ethereumjs-util: "npm:^7.1.2" + checksum: 36b38bb56e54293cc86b02cd7146c0e653235c42a765fe704e0efd9aa96c363995c201585ede798e75f974d6d123b6f775845da2c56fbce71d9d099dc03dcb16 + languageName: node + linkType: hard + +"@ethereumjs/tx@npm:^3.3.2": + version: 3.5.2 + resolution: "@ethereumjs/tx@npm:3.5.2" + dependencies: + "@ethereumjs/common": "npm:^2.6.4" + ethereumjs-util: "npm:^7.1.5" + checksum: 768cbe0834eef15f4726b44f2a4c52b6180884d90e58108d5251668c7e89d58572de7375d5e63be9d599e79c09259e643837a2afe876126b09c47ac35386cc20 + languageName: node + linkType: hard + +"@ethereumjs/util@npm:^8.1.0": + version: 8.1.0 + resolution: "@ethereumjs/util@npm:8.1.0" + dependencies: + "@ethereumjs/rlp": "npm:^4.0.1" + ethereum-cryptography: "npm:^2.0.0" + micro-ftch: "npm:^0.3.1" + checksum: 4e6e0449236f66b53782bab3b387108f0ddc050835bfe1381c67a7c038fea27cb85ab38851d98b700957022f0acb6e455ca0c634249cfcce1a116bad76500160 + languageName: node + linkType: hard + +"@ethersproject/abi@npm:5.0.0-beta.153": + version: 5.0.0-beta.153 + resolution: "@ethersproject/abi@npm:5.0.0-beta.153" + dependencies: + "@ethersproject/address": "npm:>=5.0.0-beta.128" + "@ethersproject/bignumber": "npm:>=5.0.0-beta.130" + "@ethersproject/bytes": "npm:>=5.0.0-beta.129" + "@ethersproject/constants": "npm:>=5.0.0-beta.128" + "@ethersproject/hash": "npm:>=5.0.0-beta.128" + "@ethersproject/keccak256": "npm:>=5.0.0-beta.127" + "@ethersproject/logger": "npm:>=5.0.0-beta.129" + "@ethersproject/properties": "npm:>=5.0.0-beta.131" + "@ethersproject/strings": "npm:>=5.0.0-beta.130" + checksum: 56a6b04596f75f5ac11f68963f1a3bef628732fd9e5ccc6d5752b1c1bf8fb8cdfae02aeacf5087cd40cd52d76d63d936850af55cd984e862c6998410031bef54 + languageName: node + linkType: hard + +"@ethersproject/abi@npm:5.6.0": version: 5.6.0 - resolution: "@ethersproject/wallet@npm:5.6.0" + resolution: "@ethersproject/abi@npm:5.6.0" dependencies: - "@ethersproject/abstract-provider": "npm:^5.6.0" - "@ethersproject/abstract-signer": "npm:^5.6.0" "@ethersproject/address": "npm:^5.6.0" "@ethersproject/bignumber": "npm:^5.6.0" "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/constants": "npm:^5.6.0" "@ethersproject/hash": "npm:^5.6.0" - "@ethersproject/hdnode": "npm:^5.6.0" - "@ethersproject/json-wallets": "npm:^5.6.0" "@ethersproject/keccak256": "npm:^5.6.0" "@ethersproject/logger": "npm:^5.6.0" "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/random": "npm:^5.6.0" - "@ethersproject/signing-key": "npm:^5.6.0" - "@ethersproject/transactions": "npm:^5.6.0" - "@ethersproject/wordlists": "npm:^5.6.0" - checksum: edc566bc2e8fd9201e1739cbc5dd207e902ffd58e8f054e73d631e48e50dd66c517c674fbc2028a830eece7ea08e911ee0a79f3bf19034db5951adf3bffe888a + "@ethersproject/strings": "npm:^5.6.0" + checksum: 17bfdeade4fed887b64708b409c665a034a94fc0d409b6f95498f0f752dd27306e71f1de55ce231f3fc0034f4579943e572ef742673ec6e5d69c136cbe70d942 languageName: node linkType: hard -"@ethersproject/wallet@npm:5.7.0": +"@ethersproject/abi@npm:5.7.0, @ethersproject/abi@npm:^5.0.0, @ethersproject/abi@npm:^5.1.2, @ethersproject/abi@npm:^5.5.0, @ethersproject/abi@npm:^5.6.0, @ethersproject/abi@npm:^5.6.3, @ethersproject/abi@npm:^5.7.0": version: 5.7.0 - resolution: "@ethersproject/wallet@npm:5.7.0" + resolution: "@ethersproject/abi@npm:5.7.0" dependencies: - "@ethersproject/abstract-provider": "npm:^5.7.0" - "@ethersproject/abstract-signer": "npm:^5.7.0" "@ethersproject/address": "npm:^5.7.0" "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" "@ethersproject/hash": "npm:^5.7.0" - "@ethersproject/hdnode": "npm:^5.7.0" - "@ethersproject/json-wallets": "npm:^5.7.0" "@ethersproject/keccak256": "npm:^5.7.0" "@ethersproject/logger": "npm:^5.7.0" "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/random": "npm:^5.7.0" - "@ethersproject/signing-key": "npm:^5.7.0" - "@ethersproject/transactions": "npm:^5.7.0" - "@ethersproject/wordlists": "npm:^5.7.0" - checksum: f872b957db46f9de247d39a398538622b6c7a12f93d69bec5f47f9abf0701ef1edc10497924dd1c14a68109284c39a1686fa85586d89b3ee65df49002c40ba4c + "@ethersproject/strings": "npm:^5.7.0" + checksum: 7de51bf52ff03df2526546dacea6e74f15d4c5ef762d931552082b9600dcefd8e333599f02d7906ba89f7b7f48c45ab72cee76f397212b4f17fa9d9ff5615916 languageName: node linkType: hard -"@ethersproject/web@npm:5.6.0": +"@ethersproject/abstract-provider@npm:5.6.0": version: 5.6.0 - resolution: "@ethersproject/web@npm:5.6.0" + resolution: "@ethersproject/abstract-provider@npm:5.6.0" dependencies: - "@ethersproject/base64": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" "@ethersproject/bytes": "npm:^5.6.0" "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/networks": "npm:^5.6.0" "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - checksum: 10fc728c022e664675a4e3d367c56bec465a1f7e8fd987c8eccfae57600276fd4a4fd2a86c2bf303c37939dd4480f9ccdf7249a4789297bc3bae5daee19e33c2 + "@ethersproject/transactions": "npm:^5.6.0" + "@ethersproject/web": "npm:^5.6.0" + checksum: d36fbf1f6098ef6b04a19567b8234620d19256ec77f2537d099c2b7afc666fd85c1bcdb955228fc213bfcd31e3a31e3016e1f824599a27521b81ccae22179e5b languageName: node linkType: hard -"@ethersproject/web@npm:5.7.0": +"@ethersproject/abstract-provider@npm:5.7.0, @ethersproject/abstract-provider@npm:^5.6.0, @ethersproject/abstract-provider@npm:^5.7.0": version: 5.7.0 - resolution: "@ethersproject/web@npm:5.7.0" - dependencies: - "@ethersproject/base64": "npm:^5.7.0" - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: c5cc371e7c5d58a8f8b8aaf98df3a1dff451534d49c266a847a9f2956e009fedf77281a5b65ed5f1ea3fb071bbf3f58ec07aa9159082359db063d11b23b886c5 - languageName: node - linkType: hard - -"@ethersproject/web@npm:5.7.1, @ethersproject/web@npm:^5.6.0, @ethersproject/web@npm:^5.7.0": - version: 5.7.1 - resolution: "@ethersproject/web@npm:5.7.1" + resolution: "@ethersproject/abstract-provider@npm:5.7.0" dependencies: - "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/bytes": "npm:^5.7.0" "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/networks": "npm:^5.7.0" "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: c82d6745c7f133980e8dab203955260e07da22fa544ccafdd0f21c79fae127bd6ef30957319e37b1cc80cddeb04d6bfb60f291bb14a97c9093d81ce50672f453 + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" + checksum: a5708e2811b90ddc53d9318ce152511a32dd4771aa2fb59dbe9e90468bb75ca6e695d958bf44d13da684dc3b6aab03f63d425ff7591332cb5d7ddaf68dff7224 languageName: node linkType: hard -"@ethersproject/wordlists@npm:5.6.0": +"@ethersproject/abstract-signer@npm:5.6.0": version: 5.6.0 - resolution: "@ethersproject/wordlists@npm:5.6.0" + resolution: "@ethersproject/abstract-signer@npm:5.6.0" dependencies: + "@ethersproject/abstract-provider": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/hash": "npm:^5.6.0" "@ethersproject/logger": "npm:^5.6.0" "@ethersproject/properties": "npm:^5.6.0" - "@ethersproject/strings": "npm:^5.6.0" - checksum: 47aa549e7c25cd7a995863edede77112c9af96e9aed1a9a4213c3f02f8bb025eba3de85e0da50ca7b26542867cd78f492bb1cf9c93803eb765ede54b66ba80ae + checksum: 8c84e7545fda6b7ebf2115700f5bdd6d41ba89a1547bc7fab51ce3ada4802d6ea84d5c87700c212d999ee6f8f374e8e123b1f67b08ff99dd77bd1defb633e042 languageName: node linkType: hard -"@ethersproject/wordlists@npm:5.7.0, @ethersproject/wordlists@npm:^5.6.0, @ethersproject/wordlists@npm:^5.7.0": +"@ethersproject/abstract-signer@npm:5.7.0, @ethersproject/abstract-signer@npm:^5.0.0, @ethersproject/abstract-signer@npm:^5.6.0, @ethersproject/abstract-signer@npm:^5.7.0": version: 5.7.0 - resolution: "@ethersproject/wordlists@npm:5.7.0" + resolution: "@ethersproject/abstract-signer@npm:5.7.0" dependencies: + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/hash": "npm:^5.7.0" "@ethersproject/logger": "npm:^5.7.0" "@ethersproject/properties": "npm:^5.7.0" - "@ethersproject/strings": "npm:^5.7.0" - checksum: da4f3eca6d691ebf4f578e6b2ec3a76dedba791be558f6cf7e10cd0bfbaeab5a6753164201bb72ced745fb02b6ef7ef34edcb7e6065ce2b624c6556a461c3f70 + checksum: e174966b3be17269a5974a3ae5eef6d15ac62ee8c300ceace26767f218f6bbf3de66f29d9a9c9ca300fa8551aab4c92e28d2cc772f5475fdeaa78d9b5be0e745 languageName: node linkType: hard -"@fastify/busboy@npm:^2.0.0": - version: 2.1.0 - resolution: "@fastify/busboy@npm:2.1.0" - checksum: 7bb641080aac7cf01d88749ad331af10ba9ec3713ec07cabbe833908c75df21bd56249bb6173bdec07f5a41896b21e3689316f86684c06635da45f91ff4565a2 - languageName: node +"@ethersproject/address@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/address@npm:5.6.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/keccak256": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/rlp": "npm:^5.6.0" + checksum: dada2e1d800085ef97d380f84d7a929cfccc78856ead06c122045c2bfb896cd5affb47f01fb31af70cad56172135afc93679051267847d5896f3efcb2cbba216 + languageName: node + linkType: hard + +"@ethersproject/address@npm:5.7.0, @ethersproject/address@npm:>=5.0.0-beta.128, @ethersproject/address@npm:^5.0.0, @ethersproject/address@npm:^5.0.2, @ethersproject/address@npm:^5.0.8, @ethersproject/address@npm:^5.6.0, @ethersproject/address@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/address@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + checksum: db5da50abeaae8f6cf17678323e8d01cad697f9a184b0593c62b71b0faa8d7e5c2ba14da78a998d691773ed6a8eb06701f65757218e0eaaeb134e5c5f3e5a908 + languageName: node + linkType: hard + +"@ethersproject/base64@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/base64@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + checksum: 5aa21dfae72a59495823ad89251a56813dd63160d593aa126c2dfc4bd4d650318d81e4000eff6cd1eb8cfce2494300a1bf9a96e2688e2fba642e8bc5bc7a363e + languageName: node + linkType: hard + +"@ethersproject/base64@npm:5.7.0, @ethersproject/base64@npm:^5.6.0, @ethersproject/base64@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/base64@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + checksum: 4f748cd82af60ff1866db699fbf2bf057feff774ea0a30d1f03ea26426f53293ea10cc8265cda1695301da61093bedb8cc0d38887f43ed9dad96b78f19d7337e + languageName: node + linkType: hard + +"@ethersproject/basex@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/basex@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + checksum: db108a14a7a34e538d993c8fcd18444226f9c65af80672670c784ced56b8b8e07348176394525a2675971fb30406a035dc9a3038cd478d05099712b48ba6d87f + languageName: node + linkType: hard + +"@ethersproject/basex@npm:5.7.0, @ethersproject/basex@npm:^5.6.0, @ethersproject/basex@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/basex@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + checksum: 02304de77477506ad798eb5c68077efd2531624380d770ef4a823e631a288fb680107a0f9dc4a6339b2a0b0f5b06ee77f53429afdad8f950cde0f3e40d30167d + languageName: node + linkType: hard + +"@ethersproject/bignumber@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/bignumber@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + bn.js: "npm:^4.11.9" + checksum: f8f76238d9e975a849a331f6569621bfb57c0ffb62a736e67fd129a1b1ea29c0542cb8c594fcc4fbb8cd12f2625a891ad87675aeb7f524ca7808818b884721d9 + languageName: node + linkType: hard + +"@ethersproject/bignumber@npm:5.7.0, @ethersproject/bignumber@npm:>=5.0.0-beta.130, @ethersproject/bignumber@npm:^5.0.0, @ethersproject/bignumber@npm:^5.1.1, @ethersproject/bignumber@npm:^5.6.0, @ethersproject/bignumber@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/bignumber@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + bn.js: "npm:^5.2.1" + checksum: 14263cdc91a7884b141d9300f018f76f69839c47e95718ef7161b11d2c7563163096fee69724c5fa8ef6f536d3e60f1c605819edbc478383a2b98abcde3d37b2 + languageName: node + linkType: hard + +"@ethersproject/bytes@npm:5.6.1": + version: 5.6.1 + resolution: "@ethersproject/bytes@npm:5.6.1" + dependencies: + "@ethersproject/logger": "npm:^5.6.0" + checksum: 6bc6c8d7eebfe13b2976851920bf11e6b0dcc2ee91a8e013ca6ab9b55a4de7ccf9b3c8f4cdc777547c5ddc795a8ada0bf79ca91482e88d01e3957c901c0fef55 + languageName: node + linkType: hard + +"@ethersproject/bytes@npm:5.7.0, @ethersproject/bytes@npm:>=5.0.0-beta.129, @ethersproject/bytes@npm:^5.0.0, @ethersproject/bytes@npm:^5.0.8, @ethersproject/bytes@npm:^5.6.0, @ethersproject/bytes@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/bytes@npm:5.7.0" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: 07dd1f0341b3de584ef26c8696674ff2bb032f4e99073856fc9cd7b4c54d1d846cabe149e864be267934658c3ce799e5ea26babe01f83af0e1f06c51e5ac791f + languageName: node + linkType: hard + +"@ethersproject/constants@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/constants@npm:5.6.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.6.0" + checksum: 61c8b0ceab8a3bdf10b15bd32c16343ea3149ddafaedb6698fb7fcf850e29061323cb3fcf93a00c79f33ba481f3e5e2547e1dc63ace9fe46fcdb48bf69e8d31b + languageName: node + linkType: hard + +"@ethersproject/constants@npm:5.7.0, @ethersproject/constants@npm:>=5.0.0-beta.128, @ethersproject/constants@npm:^5.6.0, @ethersproject/constants@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/constants@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.7.0" + checksum: 6df63ab753e152726b84595250ea722165a5744c046e317df40a6401f38556385a37c84dadf5b11ca651c4fb60f967046125369c57ac84829f6b30e69a096273 + languageName: node + linkType: hard + +"@ethersproject/contracts@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/contracts@npm:5.6.0" + dependencies: + "@ethersproject/abi": "npm:^5.6.0" + "@ethersproject/abstract-provider": "npm:^5.6.0" + "@ethersproject/abstract-signer": "npm:^5.6.0" + "@ethersproject/address": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/constants": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/transactions": "npm:^5.6.0" + checksum: 1a97c93acef2125cf68b1cd0bdc950188f5231e68216dcce2a81624f438713c1364c994ac600e549491bd889599e948fe96adae5bf6244667cba9d2ba1c83323 + languageName: node + linkType: hard + +"@ethersproject/contracts@npm:5.7.0, @ethersproject/contracts@npm:^5.0.0": + version: 5.7.0 + resolution: "@ethersproject/contracts@npm:5.7.0" + dependencies: + "@ethersproject/abi": "npm:^5.7.0" + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + checksum: 97a10361dddaccfb3e9e20e24d071cfa570050adcb964d3452c5f7c9eaaddb4e145ec9cf928e14417948701b89e81d4907800e799a6083123e4d13a576842f41 + languageName: node + linkType: hard + +"@ethersproject/experimental@npm:^5.0.7, @ethersproject/experimental@npm:^5.6.0, @ethersproject/experimental@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/experimental@npm:5.7.0" + dependencies: + "@ethersproject/web": "npm:^5.7.0" + ethers: "npm:^5.7.0" + scrypt-js: "npm:3.0.1" + checksum: 0546f8737ca062ce7d4a890d9cb354fde34b10b042b1d6b26e7206810c39d0fdb7ac20e60686a89f3f41faf33cc4c4c7366f49700a2d0978f0457e79759a79a4 + languageName: node + linkType: hard + +"@ethersproject/hash@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/hash@npm:5.6.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.6.0" + "@ethersproject/address": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/keccak256": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/strings": "npm:^5.6.0" + checksum: dd7dae9576dcaff1255ab2a65514e2c5f59a6a66efddc4144dc68d8f45c6bd26fdd8ed528f2cd949082526b64e2d5d8d786b9646812d310af911affc878199b4 + languageName: node + linkType: hard + +"@ethersproject/hash@npm:5.7.0, @ethersproject/hash@npm:>=5.0.0-beta.128, @ethersproject/hash@npm:^5.6.0, @ethersproject/hash@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/hash@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: 1a631dae34c4cf340dde21d6940dd1715fc7ae483d576f7b8ef9e8cb1d0e30bd7e8d30d4a7d8dc531c14164602323af2c3d51eb2204af18b2e15167e70c9a5ef + languageName: node + linkType: hard + +"@ethersproject/hdnode@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/hdnode@npm:5.6.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.6.0" + "@ethersproject/basex": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/pbkdf2": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/sha2": "npm:^5.6.0" + "@ethersproject/signing-key": "npm:^5.6.0" + "@ethersproject/strings": "npm:^5.6.0" + "@ethersproject/transactions": "npm:^5.6.0" + "@ethersproject/wordlists": "npm:^5.6.0" + checksum: 59f19629a8071366dcffae903f32ad8675640a9027541912e880bc225ed61736ebd20f774e44a586e37d79c122cffed42b3e9ec4c35db78d1d025d2e14a060ba + languageName: node + linkType: hard + +"@ethersproject/hdnode@npm:5.7.0, @ethersproject/hdnode@npm:^5.6.0, @ethersproject/hdnode@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/hdnode@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/basex": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/pbkdf2": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/sha2": "npm:^5.7.0" + "@ethersproject/signing-key": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/wordlists": "npm:^5.7.0" + checksum: 36d5c13fe69b1e0a18ea98537bc560d8ba166e012d63faac92522a0b5f405eb67d8848c5aca69e2470f62743aaef2ac36638d9e27fd8c68f51506eb61479d51d + languageName: node + linkType: hard + +"@ethersproject/json-wallets@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/json-wallets@npm:5.6.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.6.0" + "@ethersproject/address": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/hdnode": "npm:^5.6.0" + "@ethersproject/keccak256": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/pbkdf2": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/random": "npm:^5.6.0" + "@ethersproject/strings": "npm:^5.6.0" + "@ethersproject/transactions": "npm:^5.6.0" + aes-js: "npm:3.0.0" + scrypt-js: "npm:3.0.1" + checksum: 0753e152f892a06736f3c0a8d837005a393b566a6b146d818375b32377f526ee4c79d854e8168e586cf32242a640f1b10b460278fcb8eb7e1fcd5ecda1f1a974 + languageName: node + linkType: hard + +"@ethersproject/json-wallets@npm:5.7.0, @ethersproject/json-wallets@npm:^5.6.0, @ethersproject/json-wallets@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/json-wallets@npm:5.7.0" + dependencies: + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/hdnode": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/pbkdf2": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/random": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + aes-js: "npm:3.0.0" + scrypt-js: "npm:3.0.1" + checksum: f1a84d19ff38d3506f453abc4702107cbc96a43c000efcd273a056371363767a06a8d746f84263b1300266eb0c329fe3b49a9b39a37aadd016433faf9e15a4bb + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/keccak256@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + js-sha3: "npm:0.8.0" + checksum: 3f99e3bd7b1125bad4c1ac10c133c2e09b93d7675bc9a54e4b0f608520ebf20df36f6d83dd6804f2cbea3b51ffd800cc9532f7239c5e0803aa58d62d7f0d0d94 + languageName: node + linkType: hard + +"@ethersproject/keccak256@npm:5.7.0, @ethersproject/keccak256@npm:>=5.0.0-beta.127, @ethersproject/keccak256@npm:^5.6.0, @ethersproject/keccak256@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/keccak256@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + js-sha3: "npm:0.8.0" + checksum: 3b1a91706ff11f5ab5496840b9c36cedca27db443186d28b94847149fd16baecdc13f6fc5efb8359506392f2aba559d07e7f9c1e17a63f9d5de9f8053cfcb033 + languageName: node + linkType: hard + +"@ethersproject/logger@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/logger@npm:5.6.0" + checksum: f4c2610cf25d833cc1bc0a4ce99227c30508f15c8acb423e8a15f12ac25e37f9f86779485e6f79a887b24df831bdbee949249eb5feb75c6b45ca761161739516 + languageName: node + linkType: hard + +"@ethersproject/logger@npm:5.7.0, @ethersproject/logger@npm:>=5.0.0-beta.129, @ethersproject/logger@npm:^5.6.0, @ethersproject/logger@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/logger@npm:5.7.0" + checksum: d03d460fb2d4a5e71c627b7986fb9e50e1b59a6f55e8b42a545b8b92398b961e7fd294bd9c3d8f92b35d0f6ff9d15aa14c95eab378f8ea194e943c8ace343501 + languageName: node + linkType: hard + +"@ethersproject/networks@npm:5.6.1": + version: 5.6.1 + resolution: "@ethersproject/networks@npm:5.6.1" + dependencies: + "@ethersproject/logger": "npm:^5.6.0" + checksum: 3628b2a302dedbcb0c8c36f3e42faa688fdb46c7afe28ce95d02d2a5306a865b2f6c2e72ce6f701c3d15291d09e626d22910c10f39ea9016997ec1977d16a310 + languageName: node + linkType: hard + +"@ethersproject/networks@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/networks@npm:5.7.0" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: ac9f921a196bc8f7816c1ba43262bb22701f00ab599f4af8bd7275a7728b748ff428dd3445d375f7b2abdfe29bf85eff77cf132d25df8c78ff504c6b86c56e6e + languageName: node + linkType: hard + +"@ethersproject/networks@npm:5.7.1, @ethersproject/networks@npm:^5.6.0, @ethersproject/networks@npm:^5.7.0": + version: 5.7.1 + resolution: "@ethersproject/networks@npm:5.7.1" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: 9efcdce27f150459e85d74af3f72d5c32898823a99f5410e26bf26cca2d21fb14e403377314a93aea248e57fb2964e19cee2c3f7bfc586ceba4c803a8f1b75c0 + languageName: node + linkType: hard + +"@ethersproject/pbkdf2@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/pbkdf2@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/sha2": "npm:^5.6.0" + checksum: 5dbf03cb20dcd794db08dec21fc2a56feed7d13cf78d2358933ff936d6499b7d3c0169d0fde33cc0bfee31186df0db1dc732fd881499f3274964115be8140dfd + languageName: node + linkType: hard + +"@ethersproject/pbkdf2@npm:5.7.0, @ethersproject/pbkdf2@npm:^5.6.0, @ethersproject/pbkdf2@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/pbkdf2@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/sha2": "npm:^5.7.0" + checksum: e5a29cf28b4f4ca1def94d37cfb6a9c05c896106ed64881707813de01c1e7ded613f1e95febcccda4de96aae929068831d72b9d06beef1377b5a1a13a0eb3ff5 + languageName: node + linkType: hard + +"@ethersproject/properties@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/properties@npm:5.6.0" + dependencies: + "@ethersproject/logger": "npm:^5.6.0" + checksum: a137e1002d1af1e37b81279df370081c5c0fab7492fedc9798a52c10c79c6c792fef30742bc8920570cf73bfff06d6f88e89b1ef68ebbb0360d1d8f1efa8fba9 + languageName: node + linkType: hard + +"@ethersproject/properties@npm:5.7.0, @ethersproject/properties@npm:>=5.0.0-beta.131, @ethersproject/properties@npm:^5.6.0, @ethersproject/properties@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/properties@npm:5.7.0" + dependencies: + "@ethersproject/logger": "npm:^5.7.0" + checksum: 4fe5d36e5550b8e23a305aa236a93e8f04d891d8198eecdc8273914c761b0e198fd6f757877406ee3eb05033ec271132a3e5998c7bd7b9a187964fb4f67b1373 + languageName: node + linkType: hard + +"@ethersproject/providers@npm:5.6.2": + version: 5.6.2 + resolution: "@ethersproject/providers@npm:5.6.2" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.6.0" + "@ethersproject/abstract-signer": "npm:^5.6.0" + "@ethersproject/address": "npm:^5.6.0" + "@ethersproject/basex": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/constants": "npm:^5.6.0" + "@ethersproject/hash": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/networks": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/random": "npm:^5.6.0" + "@ethersproject/rlp": "npm:^5.6.0" + "@ethersproject/sha2": "npm:^5.6.0" + "@ethersproject/strings": "npm:^5.6.0" + "@ethersproject/transactions": "npm:^5.6.0" + "@ethersproject/web": "npm:^5.6.0" + bech32: "npm:1.1.4" + ws: "npm:7.4.6" + checksum: 9dc8c5ff0227cc7e377e7dac42f3191b9ff4430921069025beb531d0640b93d139ae4499f098711fd3212ad77ec6c0c403780c993fd2101e05ff40e2e9cf24a4 + languageName: node + linkType: hard + +"@ethersproject/providers@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/providers@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/basex": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/networks": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/random": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/sha2": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" + bech32: "npm:1.1.4" + ws: "npm:7.4.6" + checksum: 6da22fc08ee84d4f4ca806ab86d8ea17e031a820767c44190136a5210fb8962ea0531f06eeec5da0ab2d06eef815234be2f98ec017b1d3cac4c7fc511dfb5b4b + languageName: node + linkType: hard + +"@ethersproject/providers@npm:5.7.2, @ethersproject/providers@npm:^5.0.0, @ethersproject/providers@npm:^5.7.1, @ethersproject/providers@npm:^5.7.2": + version: 5.7.2 + resolution: "@ethersproject/providers@npm:5.7.2" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/basex": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/networks": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/random": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/sha2": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/web": "npm:^5.7.0" + bech32: "npm:1.1.4" + ws: "npm:7.4.6" + checksum: 4c8d19e6b31f769c24042fb2d02e483a4ee60dcbfca9e3291f0a029b24337c47d1ea719a390be856f8fd02997125819e834415e77da4fb2023369712348dae4c + languageName: node + linkType: hard + +"@ethersproject/random@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/random@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + checksum: 85f56fcd572f158a9cbc7ca27d4f139bdb6073b1a5859940cbb6d11ffdb5d9a8b7adf812d726e590947ec2eb99ed7b86c06fcef081e0edb8ed7b7753ee84a02c + languageName: node + linkType: hard + +"@ethersproject/random@npm:5.7.0, @ethersproject/random@npm:^5.6.0, @ethersproject/random@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/random@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + checksum: 23e572fc55372653c22062f6a153a68c2e2d3200db734cd0d39621fbfd0ca999585bed2d5682e3ac65d87a2893048375682e49d1473d9965631ff56d2808580b + languageName: node + linkType: hard + +"@ethersproject/rlp@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/rlp@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + checksum: f6d505fb0af334332f5a098c6e3969646e91d17a85b68db4e26228dd3866ac439e693c35337c5153e1b9e25f54c1e6c608548062fd0e7b5e9dc30c9ba8c553bd + languageName: node + linkType: hard + +"@ethersproject/rlp@npm:5.7.0, @ethersproject/rlp@npm:^5.6.0, @ethersproject/rlp@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/rlp@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + checksum: bc863d21dcf7adf6a99ae75c41c4a3fb99698cfdcfc6d5d82021530f3d3551c6305bc7b6f0475ad6de6f69e91802b7e872bee48c0596d98969aefcf121c2a044 + languageName: node + linkType: hard + +"@ethersproject/sha2@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/sha2@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + hash.js: "npm:1.1.7" + checksum: a56818968c89213146f57cadfc20949157dbb6643fb6d40f4a6cd7fb4b0433d5e679cc5b7b9e2efa5a7c20ae6e7f634ac8f7f560431f158aa94b05d621c3b1f8 + languageName: node + linkType: hard + +"@ethersproject/sha2@npm:5.7.0, @ethersproject/sha2@npm:^5.6.0, @ethersproject/sha2@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/sha2@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + hash.js: "npm:1.1.7" + checksum: 0e7f9ce6b1640817b921b9c6dd9dab8d5bf5a0ce7634d6a7d129b7366a576c2f90dcf4bcb15a0aa9310dde67028f3a44e4fcc2f26b565abcd2a0f465116ff3b1 + languageName: node + linkType: hard + +"@ethersproject/signing-key@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/signing-key@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + bn.js: "npm:^4.11.9" + elliptic: "npm:6.5.4" + hash.js: "npm:1.1.7" + checksum: 23da06746809652486458dc91c7df9f10a1e96653a70df40f8b51330cb1dba26e7f0270212ba029ff70a90cde94c48ef9fd2bae5d24d442e00e0b3f9ace4fd10 + languageName: node + linkType: hard + +"@ethersproject/signing-key@npm:5.7.0, @ethersproject/signing-key@npm:^5.6.0, @ethersproject/signing-key@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/signing-key@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + bn.js: "npm:^5.2.1" + elliptic: "npm:6.5.4" + hash.js: "npm:1.1.7" + checksum: fe2ca55bcdb6e370d81372191d4e04671234a2da872af20b03c34e6e26b97dc07c1ee67e91b673680fb13344c9d5d7eae52f1fa6117733a3d68652b778843e09 + languageName: node + linkType: hard + +"@ethersproject/solidity@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/solidity@npm:5.6.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/keccak256": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/sha2": "npm:^5.6.0" + "@ethersproject/strings": "npm:^5.6.0" + checksum: df4dbc47a88783312f783d30a7bde523e55a4007ee5918606cd0178b4ba569cee42b7e6b8f04b8b911b648bb6eda6a51b5fae6e56e0303d69d35bff725417061 + languageName: node + linkType: hard + +"@ethersproject/solidity@npm:5.7.0, @ethersproject/solidity@npm:^5.0.0": + version: 5.7.0 + resolution: "@ethersproject/solidity@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/sha2": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: bedf9918911144b0ec352b8aa7fa44abf63f0b131629c625672794ee196ba7d3992b0e0d3741935ca176813da25b9bcbc81aec454652c63113bdc3a1706beac6 + languageName: node + linkType: hard + +"@ethersproject/strings@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/strings@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/constants": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + checksum: bd0fea07ac99365b4da10654419415c88ad319d8229a9b0fbd26632ed9549fb033e6cd491c5504d437718173254247628d223ebcab6d29e3ab9046b66563fdba + languageName: node + linkType: hard + +"@ethersproject/strings@npm:5.7.0, @ethersproject/strings@npm:>=5.0.0-beta.130, @ethersproject/strings@npm:^5.6.0, @ethersproject/strings@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/strings@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + checksum: 570d87040ccc7d94de9861f76fc2fba6c0b84c5d6104a99a5c60b8a2401df2e4f24bf9c30afa536163b10a564a109a96f02e6290b80e8f0c610426f56ad704d1 + languageName: node + linkType: hard + +"@ethersproject/transactions@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/transactions@npm:5.6.0" + dependencies: + "@ethersproject/address": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/constants": "npm:^5.6.0" + "@ethersproject/keccak256": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/rlp": "npm:^5.6.0" + "@ethersproject/signing-key": "npm:^5.6.0" + checksum: 23eecd1d9892dd5decd1720fe52ca84c2dda1629834ae1c399582d230130c91aef5d839cc6e67ad2916fe2acfd83cebd5f9dd534e2a808b10cd3360b4032b588 + languageName: node + linkType: hard + +"@ethersproject/transactions@npm:5.7.0, @ethersproject/transactions@npm:^5.0.0, @ethersproject/transactions@npm:^5.0.0-beta.135, @ethersproject/transactions@npm:^5.6.0, @ethersproject/transactions@npm:^5.6.2, @ethersproject/transactions@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/transactions@npm:5.7.0" + dependencies: + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/rlp": "npm:^5.7.0" + "@ethersproject/signing-key": "npm:^5.7.0" + checksum: aa4d51379caab35b9c468ed1692a23ae47ce0de121890b4f7093c982ee57e30bd2df0c743faed0f44936d7e59c55fffd80479f2c28ec6777b8de06bfb638c239 + languageName: node + linkType: hard + +"@ethersproject/units@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/units@npm:5.6.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/constants": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + checksum: cb92acc910e00030009de917d9a7cea72def0536aceaaa9132d3d9fcedf4b39c7645ffc3950e747763a01048bb16ccd34cb0f0d6916d4d6a209ea809180a76be + languageName: node + linkType: hard + +"@ethersproject/units@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/units@npm:5.7.0" + dependencies: + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + checksum: 4da2fdefe2a506cc9f8b408b2c8638ab35b843ec413d52713143f08501a55ff67a808897f9a91874774fb526423a0821090ba294f93e8bf4933a57af9677ac5e + languageName: node + linkType: hard + +"@ethersproject/wallet@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/wallet@npm:5.6.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.6.0" + "@ethersproject/abstract-signer": "npm:^5.6.0" + "@ethersproject/address": "npm:^5.6.0" + "@ethersproject/bignumber": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/hash": "npm:^5.6.0" + "@ethersproject/hdnode": "npm:^5.6.0" + "@ethersproject/json-wallets": "npm:^5.6.0" + "@ethersproject/keccak256": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/random": "npm:^5.6.0" + "@ethersproject/signing-key": "npm:^5.6.0" + "@ethersproject/transactions": "npm:^5.6.0" + "@ethersproject/wordlists": "npm:^5.6.0" + checksum: edc566bc2e8fd9201e1739cbc5dd207e902ffd58e8f054e73d631e48e50dd66c517c674fbc2028a830eece7ea08e911ee0a79f3bf19034db5951adf3bffe888a + languageName: node + linkType: hard + +"@ethersproject/wallet@npm:5.7.0, @ethersproject/wallet@npm:^5.0.0": + version: 5.7.0 + resolution: "@ethersproject/wallet@npm:5.7.0" + dependencies: + "@ethersproject/abstract-provider": "npm:^5.7.0" + "@ethersproject/abstract-signer": "npm:^5.7.0" + "@ethersproject/address": "npm:^5.7.0" + "@ethersproject/bignumber": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/hdnode": "npm:^5.7.0" + "@ethersproject/json-wallets": "npm:^5.7.0" + "@ethersproject/keccak256": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/random": "npm:^5.7.0" + "@ethersproject/signing-key": "npm:^5.7.0" + "@ethersproject/transactions": "npm:^5.7.0" + "@ethersproject/wordlists": "npm:^5.7.0" + checksum: f872b957db46f9de247d39a398538622b6c7a12f93d69bec5f47f9abf0701ef1edc10497924dd1c14a68109284c39a1686fa85586d89b3ee65df49002c40ba4c + languageName: node + linkType: hard + +"@ethersproject/web@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/web@npm:5.6.0" + dependencies: + "@ethersproject/base64": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/strings": "npm:^5.6.0" + checksum: 10fc728c022e664675a4e3d367c56bec465a1f7e8fd987c8eccfae57600276fd4a4fd2a86c2bf303c37939dd4480f9ccdf7249a4789297bc3bae5daee19e33c2 + languageName: node + linkType: hard + +"@ethersproject/web@npm:5.7.0": + version: 5.7.0 + resolution: "@ethersproject/web@npm:5.7.0" + dependencies: + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: c5cc371e7c5d58a8f8b8aaf98df3a1dff451534d49c266a847a9f2956e009fedf77281a5b65ed5f1ea3fb071bbf3f58ec07aa9159082359db063d11b23b886c5 + languageName: node + linkType: hard + +"@ethersproject/web@npm:5.7.1, @ethersproject/web@npm:^5.6.0, @ethersproject/web@npm:^5.7.0": + version: 5.7.1 + resolution: "@ethersproject/web@npm:5.7.1" + dependencies: + "@ethersproject/base64": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: c82d6745c7f133980e8dab203955260e07da22fa544ccafdd0f21c79fae127bd6ef30957319e37b1cc80cddeb04d6bfb60f291bb14a97c9093d81ce50672f453 + languageName: node + linkType: hard + +"@ethersproject/wordlists@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/wordlists@npm:5.6.0" + dependencies: + "@ethersproject/bytes": "npm:^5.6.0" + "@ethersproject/hash": "npm:^5.6.0" + "@ethersproject/logger": "npm:^5.6.0" + "@ethersproject/properties": "npm:^5.6.0" + "@ethersproject/strings": "npm:^5.6.0" + checksum: 47aa549e7c25cd7a995863edede77112c9af96e9aed1a9a4213c3f02f8bb025eba3de85e0da50ca7b26542867cd78f492bb1cf9c93803eb765ede54b66ba80ae + languageName: node + linkType: hard + +"@ethersproject/wordlists@npm:5.7.0, @ethersproject/wordlists@npm:^5.6.0, @ethersproject/wordlists@npm:^5.7.0": + version: 5.7.0 + resolution: "@ethersproject/wordlists@npm:5.7.0" + dependencies: + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/hash": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + "@ethersproject/properties": "npm:^5.7.0" + "@ethersproject/strings": "npm:^5.7.0" + checksum: da4f3eca6d691ebf4f578e6b2ec3a76dedba791be558f6cf7e10cd0bfbaeab5a6753164201bb72ced745fb02b6ef7ef34edcb7e6065ce2b624c6556a461c3f70 + languageName: node + linkType: hard + +"@fastify/busboy@npm:^2.0.0": + version: 2.1.0 + resolution: "@fastify/busboy@npm:2.1.0" + checksum: 7bb641080aac7cf01d88749ad331af10ba9ec3713ec07cabbe833908c75df21bd56249bb6173bdec07f5a41896b21e3689316f86684c06635da45f91ff4565a2 + languageName: node + linkType: hard + +"@fastify/deepmerge@npm:^1.0.0": + version: 1.3.0 + resolution: "@fastify/deepmerge@npm:1.3.0" + checksum: 8115ed7b891189ee4ebba554a105cb69111615bdb2961f8c58a80872fac9d7b74b2c6317d545a7d378325d094ce73a91fc9c5d7d6189476779cd5a5493cb1351 + languageName: node + linkType: hard + +"@graphprotocol/client-add-source-name@npm:^1.0.20": + version: 1.0.20 + resolution: "@graphprotocol/client-add-source-name@npm:1.0.20" + dependencies: + lodash: "npm:^4.17.21" + tslib: "npm:^2.4.0" + peerDependencies: + "@graphql-mesh/types": ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 + "@graphql-tools/delegate": ^9.0.32 + "@graphql-tools/utils": ^9.2.1 + "@graphql-tools/wrap": ^9.4.2 + graphql: ^15.2.0 || ^16.0.0 + checksum: abe068a25115840ad673564eea2818622f9dc815dba1678bf665b57dbd13bfbdd34cf50a71a1e0ab9f1c7f913143935d9b06942a22a71516b6f2445d2d8be263 + languageName: node + linkType: hard + +"@graphprotocol/client-auto-pagination@npm:^1.1.18": + version: 1.1.18 + resolution: "@graphprotocol/client-auto-pagination@npm:1.1.18" + dependencies: + lodash: "npm:^4.17.21" + tslib: "npm:^2.4.0" + peerDependencies: + "@graphql-mesh/types": ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 + "@graphql-tools/delegate": ^9.0.32 + "@graphql-tools/utils": ^9.2.1 + "@graphql-tools/wrap": ^9.4.2 + graphql: ^15.2.0 || ^16.0.0 + checksum: 7e67592c28fe81452cccc43645b88ebc2f7cb44b632b69b4130a98dcd63fae42070875bd9f0ba4b40c1f3636e22168d2a6caba37b7846d4943d8af63c1a94c06 + languageName: node + linkType: hard + +"@graphprotocol/client-auto-type-merging@npm:^1.0.25": + version: 1.0.25 + resolution: "@graphprotocol/client-auto-type-merging@npm:1.0.25" + dependencies: + "@graphql-mesh/transform-type-merging": "npm:^0.93.0" + tslib: "npm:^2.4.0" + peerDependencies: + "@graphql-mesh/types": ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 + "@graphql-tools/delegate": ^9.0.32 + graphql: ^15.2.0 || ^16.0.0 + checksum: 023330de8328c191acc6a874f976652f588f86fc0aeed7160143abfd28309101e9c06f4f48925cb33a6c9b1f0f0efee11914a12631c169914f72e0740038ab34 + languageName: node + linkType: hard + +"@graphprotocol/client-block-tracking@npm:^1.0.14": + version: 1.0.14 + resolution: "@graphprotocol/client-block-tracking@npm:1.0.14" + dependencies: + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + peerDependencies: + "@graphql-tools/delegate": ^9.0.32 + graphql: ^15.2.0 || ^16.0.0 + checksum: 3468dabc76c4f062b060cae74ad26c826968a328ca4690c55a53d71f726784f63562f6b2eab9edf9a4a1318c62b90cc90745b8ca0ea8ea169876294603e5afcb + languageName: node + linkType: hard + +"@graphprotocol/client-cli@npm:^2.0.2": + version: 2.2.22 + resolution: "@graphprotocol/client-cli@npm:2.2.22" + dependencies: + "@graphprotocol/client-add-source-name": "npm:^1.0.20" + "@graphprotocol/client-auto-pagination": "npm:^1.1.18" + "@graphprotocol/client-auto-type-merging": "npm:^1.0.25" + "@graphprotocol/client-block-tracking": "npm:^1.0.14" + "@graphprotocol/client-polling-live": "npm:^1.1.1" + "@graphql-mesh/cli": "npm:^0.82.33" + "@graphql-mesh/graphql": "npm:^0.93.0" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + bin: + graphclient: cjs/bin.js + checksum: 4ea8473f902c73ce1b3d76f653814ae0dced279150f15de6123e750d1609a45326455b622818e9000aeb939ba6dd48e4b8c1efac8ee151e885dd1182450d0e87 + languageName: node + linkType: hard + +"@graphprotocol/client-polling-live@npm:^1.1.1": + version: 1.1.1 + resolution: "@graphprotocol/client-polling-live@npm:1.1.1" + dependencies: + "@repeaterjs/repeater": "npm:^3.0.4" + tslib: "npm:^2.4.0" + peerDependencies: + "@envelop/core": ^2.4.2 || ^3.0.0 + "@graphql-tools/merge": ^8.3.14 + graphql: ^15.2.0 || ^16.0.0 + checksum: 48552eca3ac5d84e8ee23a84877a6bb5dbbc06214974a311f7d7eeae1c880c0d41f56871934c2d278a260188444698299414152bde9fc4088c1abf07b7c7cf80 + languageName: node + linkType: hard + +"@graphprotocol/common-ts@npm:^1.8.3": + version: 1.8.7 + resolution: "@graphprotocol/common-ts@npm:1.8.7" + dependencies: + "@graphprotocol/contracts": "npm:2.1.0" + "@graphprotocol/pino-sentry-simple": "npm:0.7.1" + "@urql/core": "npm:2.4.4" + "@urql/exchange-execute": "npm:1.2.2" + body-parser: "npm:1.19.1" + bs58: "npm:4.0.1" + cors: "npm:2.8.5" + cross-fetch: "npm:3.1.5" + ethers: "npm:5.6.2" + express: "npm:4.17.3" + graphql: "npm:16.3.0" + graphql-tag: "npm:2.12.6" + helmet: "npm:5.0.2" + morgan: "npm:1.10.0" + ngeohash: "npm:0.6.3" + pg: "npm:8.7.3" + pg-hstore: "npm:2.3.4" + pino: "npm:7.6.0" + pino-multi-stream: "npm:6.0.0" + prom-client: "npm:14.0.1" + sequelize: "npm:6.19.0" + checksum: 64a974245e47bc0937ee1e7905886530786ae61fcea4e1566193466446c1bc0a18f7a7570826a1defb6c05edddb7b82f3da7a33ab5e2ce4df90340eb5d78a0ce + languageName: node + linkType: hard + +"@graphprotocol/common-ts@npm:^2.0.7": + version: 2.0.9 + resolution: "@graphprotocol/common-ts@npm:2.0.9" + dependencies: + "@graphprotocol/contracts": "npm:5.3.3" + "@graphprotocol/pino-sentry-simple": "npm:0.7.1" + "@urql/core": "npm:2.4.4" + "@urql/exchange-execute": "npm:1.2.2" + body-parser: "npm:1.20.2" + bs58: "npm:5.0.0" + cors: "npm:2.8.5" + cross-fetch: "npm:4.0.0" + ethers: "npm:5.7.0" + express: "npm:4.18.2" + graphql: "npm:16.8.0" + graphql-tag: "npm:2.12.6" + helmet: "npm:7.0.0" + morgan: "npm:1.10.0" + ngeohash: "npm:0.6.3" + pg: "npm:8.11.3" + pg-hstore: "npm:2.3.4" + pino: "npm:7.6.0" + pino-multi-stream: "npm:6.0.0" + prom-client: "npm:14.2.0" + sequelize: "npm:6.33.0" + checksum: b0009fbfcd0eb86f411627ef4cb974b1cee33922610f7636833e4b56cb9ca5652161115072e880b06e2ab500c34068d3d2f193395d0b16f69a5562d2b7585c74 + languageName: node + linkType: hard + +"@graphprotocol/contracts-monorepo@workspace:.": + version: 0.0.0-use.local + resolution: "@graphprotocol/contracts-monorepo@workspace:." + dependencies: + "@changesets/cli": "npm:^2.27.1" + "@commitlint/cli": "npm:^18.4.3" + "@commitlint/config-conventional": "npm:^18.4.3" + husky: "npm:^8.0.3" + languageName: unknown + linkType: soft + +"@graphprotocol/contracts@npm:2.1.0": + version: 2.1.0 + resolution: "@graphprotocol/contracts@npm:2.1.0" + dependencies: + console-table-printer: "npm:^2.11.1" + ethers: "npm:^5.6.0" + checksum: 948c7f667b9e7efb83b06e06fd7218d044b8a1c8fed37a555f784d9ef2ef6c840306d64163dd1d82657d61d2edb563eff35af9b96bb2ef9e76ea59a6b46b6282 + languageName: node + linkType: hard + +"@graphprotocol/contracts@npm:5.3.3, @graphprotocol/contracts@npm:^5.0.0": + version: 5.3.3 + resolution: "@graphprotocol/contracts@npm:5.3.3" + dependencies: + console-table-printer: "npm:^2.11.1" + ethers: "npm:^5.6.0" + checksum: 00d5fd682e829da8747eaebc65645b660e7551234fbd8a05f72b7b75ce6537dbfe51e410d84eeaa4dfe7dc87c16c276b50c30fcb6d528c83fa42698acc306af3 + languageName: node + linkType: hard + +"@graphprotocol/contracts@workspace:^6.2.0, @graphprotocol/contracts@workspace:packages/contracts": + version: 0.0.0-use.local + resolution: "@graphprotocol/contracts@workspace:packages/contracts" + dependencies: + "@arbitrum/sdk": "npm:~3.1.13" + "@defi-wonderland/smock": "npm:^2.0.7" + "@ethersproject/experimental": "npm:^5.6.0" + "@graphprotocol/common-ts": "npm:^1.8.3" + "@graphprotocol/sdk": "workspace:^0.5.0" + "@nomiclabs/hardhat-ethers": "npm:^2.2.3" + "@nomiclabs/hardhat-etherscan": "npm:^3.1.7" + "@nomiclabs/hardhat-waffle": "npm:2.0.3" + "@openzeppelin/contracts": "npm:^3.4.1" + "@openzeppelin/contracts-upgradeable": "npm:3.4.2" + "@openzeppelin/hardhat-defender": "npm:^1.8.1" + "@openzeppelin/hardhat-upgrades": "npm:^1.6.0" + "@tenderly/hardhat-tenderly": "npm:1.0.13" + "@typechain/ethers-v5": "npm:^7.0.0" + "@typechain/hardhat": "npm:^2.0.0" + "@types/bs58": "npm:^4.0.1" + "@types/chai-as-promised": "npm:^7.1.5" + "@types/dotenv": "npm:^8.2.0" + "@types/glob": "npm:^7.2.0" + "@types/inquirer": "npm:^7.3.1" + "@types/minimist": "npm:^1.2.1" + "@types/mocha": "npm:^8.2.2" + "@types/node": "npm:^20.9.0" + "@types/sinon-chai": "npm:^3.2.12" + "@types/winston": "npm:^2.4.4" + "@types/yargs": "npm:^16.0.0" + "@urql/core": "npm:^2.1.3" + arbos-precompiles: "npm:^1.0.2" + bignumber.js: "npm:^9.0.0" + chai: "npm:^4.3.4" + chai-as-promised: "npm:^7.1.1" + cli-table: "npm:^0.3.6" + console-table-printer: "npm:^2.11.1" + dotenv: "npm:^9.0.0" + eslint: "npm:^8.57.0" + eslint-graph-config: "workspace:^0.0.1" + ethereum-waffle: "npm:^3.2.0" + ethers: "npm:^5.7.2" + form-data: "npm:^4.0.0" + glob: "npm:^8.0.3" + graphql-tag: "npm:^2.12.4" + hardhat: "npm:~2.14.0" + hardhat-abi-exporter: "npm:^2.2.0" + hardhat-contract-sizer: "npm:^2.0.3" + hardhat-gas-reporter: "npm:^1.0.4" + hardhat-secure-accounts: "npm:0.0.5" + hardhat-storage-layout: "npm:0.1.6" + hardhat-tracer: "npm:^1.0.0-alpha.6" + inquirer: "npm:^8.0.0" + ipfs-http-client: "npm:47.0.1" + isomorphic-fetch: "npm:^3.0.0" + lint-staged: "npm:^10.5.4" + p-queue: "npm:^6.6.1" + prettier: "npm:^3.2.5" + prettier-plugin-solidity: "npm:^1.3.1" + solhint: "npm:^4.1.1" + solhint-graph-config: "workspace:^0.0.1" + solidity-coverage: "npm:^0.7.16" + ts-node: "npm:^10.9.1" + typechain: "npm:^5.0.0" + typescript: "npm:^4.7.4" + winston: "npm:^3.3.3" + yaml: "npm:^1.10.2" + yargs: "npm:^17.0.0" + languageName: unknown + linkType: soft + +"@graphprotocol/pino-sentry-simple@npm:0.7.1": + version: 0.7.1 + resolution: "@graphprotocol/pino-sentry-simple@npm:0.7.1" + dependencies: + "@sentry/node": "npm:^5.21.1" + pumpify: "npm:^2.0.1" + split2: "npm:^3.1.1" + through2: "npm:^3.0.1" + checksum: 4aad42ecc41ebc7a447f03e351ce10034619da119f1d427231f7abc329050bbe34b44d88f92c0e7f41e879541bc747c1814b3fe3a32d3b8fdafb7acfc7635202 + languageName: node + linkType: hard + +"@graphprotocol/sdk@workspace:^0.5.0, @graphprotocol/sdk@workspace:packages/sdk": + version: 0.0.0-use.local + resolution: "@graphprotocol/sdk@workspace:packages/sdk" + dependencies: + "@arbitrum/sdk": "npm:~3.1.13" + "@ethersproject/experimental": "npm:^5.7.0" + "@graphprotocol/common-ts": "npm:^2.0.7" + "@graphprotocol/contracts": "workspace:^6.2.0" + "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.9" + "@nomiclabs/hardhat-ethers": "npm:^2.2.3" + "@types/chai": "npm:^4.3.9" + "@types/chai-as-promised": "npm:^7.1.7" + "@types/debug": "npm:^4.1.10" + "@types/inquirer": "npm:^8.0.0" + "@types/lodash": "npm:^4.14.200" + "@types/mocha": "npm:^10.0.3" + "@types/node": "npm:^20.8.7" + "@typescript-eslint/eslint-plugin": "npm:^6.8.0" + "@typescript-eslint/parser": "npm:^6.8.0" + chai: "npm:^4.3.10" + chai-as-promised: "npm:^7.1.1" + debug: "npm:^4.3.4" + eslint: "npm:^8.52.0" + eslint-config-prettier: "npm:^9.0.0" + eslint-plugin-no-only-tests: "npm:^3.1.0" + eslint-plugin-prettier: "npm:^5.0.1" + ethers: "npm:^5.7.0" + hardhat: "npm:~2.14.0" + hardhat-secure-accounts: "npm:^0.0.6" + inquirer: "npm:^8.0.0" + lodash: "npm:^4.17.21" + prettier: "npm:^3.0.3" + ts-node: "npm:^10.9.1" + typescript: "npm:^5.1.6" + yaml: "npm:^1.10.2" + languageName: unknown + linkType: soft + +"@graphprotocol/token-distribution@workspace:packages/token-distribution": + version: 0.0.0-use.local + resolution: "@graphprotocol/token-distribution@workspace:packages/token-distribution" + dependencies: + "@ethersproject/experimental": "npm:^5.0.7" + "@graphprotocol/client-cli": "npm:^2.0.2" + "@graphprotocol/contracts": "npm:^5.0.0" + "@nomiclabs/hardhat-ethers": "npm:^2.0.0" + "@nomiclabs/hardhat-etherscan": "npm:^3.1.7" + "@nomiclabs/hardhat-waffle": "npm:^2.0.0" + "@openzeppelin/contracts": "npm:^3.3.0-solc-0.7" + "@openzeppelin/contracts-upgradeable": "npm:3.4.2" + "@openzeppelin/hardhat-upgrades": "npm:^1.22.1" + "@typechain/ethers-v5": "npm:^7.0.0" + "@typechain/hardhat": "npm:^2.0.0" + "@types/mocha": "npm:^9.1.0" + "@types/node": "npm:^20.4.2" + chai: "npm:^4.2.0" + coingecko-api: "npm:^1.0.10" + consola: "npm:^2.15.0" + dotenv: "npm:^16.0.0" + eslint: "npm:^8.56.0" + eslint-graph-config: "workspace:^" + ethereum-waffle: "npm:^3.1.1" + ethers: "npm:^5.0.18" + graphql: "npm:^16.5.0" + hardhat: "npm:^2.6.1" + hardhat-abi-exporter: "npm:^2.0.1" + hardhat-contract-sizer: "npm:^2.0.1" + hardhat-deploy: "npm:^0.7.0-beta.9" + hardhat-gas-reporter: "npm:^1.0.1" + inquirer: "npm:8.0.0" + p-queue: "npm:^6.6.2" + prettier: "npm:^3.2.5" + prettier-plugin-solidity: "npm:^1.3.1" + solhint-community: "npm:^3.7.0" + solhint-graph-config: "workspace:^0.0.1" + solhint-plugin-prettier: "npm:^0.1.0" + ts-node: "npm:^10.9.1" + typechain: "npm:^5.0.0" + typescript: "npm:^4.0.2" + languageName: unknown + linkType: soft + +"@graphql-codegen/core@npm:^3.1.0": + version: 3.1.0 + resolution: "@graphql-codegen/core@npm:3.1.0" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^4.1.0" + "@graphql-tools/schema": "npm:^9.0.0" + "@graphql-tools/utils": "npm:^9.1.1" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 822be191eba5cc9f1882936501941054adfc517cb7f32e32c85843253eec268eca20d24f2ba04d9575719e36e3a5cd0df059715f3fd78d32f12f7d79c7198e79 + languageName: node + linkType: hard + +"@graphql-codegen/plugin-helpers@npm:^2.7.2": + version: 2.7.2 + resolution: "@graphql-codegen/plugin-helpers@npm:2.7.2" + dependencies: + "@graphql-tools/utils": "npm:^8.8.0" + change-case-all: "npm:1.0.14" + common-tags: "npm:1.8.2" + import-from: "npm:4.0.0" + lodash: "npm:~4.17.0" + tslib: "npm:~2.4.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: b4abce50a751d938a48b2b7ff57aa1671df1ae9d54196ccd60237077aef2e2b528b45244cb786d1b2eeb1f464c48eb7626553fdc5cf3a9013455ed27ef3ef7d2 + languageName: node + linkType: hard + +"@graphql-codegen/plugin-helpers@npm:^3.0.0": + version: 3.1.2 + resolution: "@graphql-codegen/plugin-helpers@npm:3.1.2" + dependencies: + "@graphql-tools/utils": "npm:^9.0.0" + change-case-all: "npm:1.0.15" + common-tags: "npm:1.8.2" + import-from: "npm:4.0.0" + lodash: "npm:~4.17.0" + tslib: "npm:~2.4.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: fbe326270aef17792b326ad8d8ae3e82acf1b60f3137a4d99eb605c0c8d709830537fec112705484b5fd2c9ee1d0588fbf4269f31c9a5852567c5d4c0c7057b7 + languageName: node + linkType: hard + +"@graphql-codegen/plugin-helpers@npm:^4.1.0, @graphql-codegen/plugin-helpers@npm:^4.2.0": + version: 4.2.0 + resolution: "@graphql-codegen/plugin-helpers@npm:4.2.0" + dependencies: + "@graphql-tools/utils": "npm:^9.0.0" + change-case-all: "npm:1.0.15" + common-tags: "npm:1.8.2" + import-from: "npm:4.0.0" + lodash: "npm:~4.17.0" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: cc4a63eb6cd015c9b26f6ff115257ff9c7b87c352a23b3f0622536c6df693e647ff627daef6f370c629fc515ddfdb2f7e3190f5e8cd6490a1ea513835cc358c3 + languageName: node + linkType: hard + +"@graphql-codegen/schema-ast@npm:^3.0.1": + version: 3.0.1 + resolution: "@graphql-codegen/schema-ast@npm:3.0.1" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^4.1.0" + "@graphql-tools/utils": "npm:^9.0.0" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: cc4602e5b97876181e6a8e3e0241e336715e489d1721121037a0a28b49d3bd800de9a331c8db2e9449c3c237e842c05db93a2c834cfcc7e3cd68a15c96a8e204 + languageName: node + linkType: hard + +"@graphql-codegen/typed-document-node@npm:^4.0.1": + version: 4.0.1 + resolution: "@graphql-codegen/typed-document-node@npm:4.0.1" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^4.2.0" + "@graphql-codegen/visitor-plugin-common": "npm:3.1.1" + auto-bind: "npm:~4.0.0" + change-case-all: "npm:1.0.15" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: ffa1416f7958c50845f24b59e91da488e7010d23ec2eddfb602822e08d420e7a1805eebcb2aa1eb14928515b6099410cee4c172ec3fa54496a052d0f839b9f3b + languageName: node + linkType: hard + +"@graphql-codegen/typescript-generic-sdk@npm:^3.1.0": + version: 3.1.0 + resolution: "@graphql-codegen/typescript-generic-sdk@npm:3.1.0" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^3.0.0" + "@graphql-codegen/visitor-plugin-common": "npm:2.13.1" + auto-bind: "npm:~4.0.0" + tslib: "npm:~2.4.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + graphql-tag: ^2.0.0 + checksum: 9423c37e5d01b862026a76c8b52e6d27395a60169caa509179107396df03d9cadaca0f1e875be9e42acb771af598c58104a2fce7ff75952632ee03b381903ccf + languageName: node + linkType: hard + +"@graphql-codegen/typescript-operations@npm:^3.0.4": + version: 3.0.4 + resolution: "@graphql-codegen/typescript-operations@npm:3.0.4" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^4.2.0" + "@graphql-codegen/typescript": "npm:^3.0.4" + "@graphql-codegen/visitor-plugin-common": "npm:3.1.1" + auto-bind: "npm:~4.0.0" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 4ea5c955e0b12b1f6aa4d6ad46b217c56e802ff5508b939a3a218c53208d03bbd308bb3dfbfbc30fe7c4bd0be4c9c51c76b0fe65c6238618ed482874c869f801 + languageName: node + linkType: hard + +"@graphql-codegen/typescript-resolvers@npm:^3.2.1": + version: 3.2.1 + resolution: "@graphql-codegen/typescript-resolvers@npm:3.2.1" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^4.2.0" + "@graphql-codegen/typescript": "npm:^3.0.4" + "@graphql-codegen/visitor-plugin-common": "npm:3.1.1" + "@graphql-tools/utils": "npm:^9.0.0" + auto-bind: "npm:~4.0.0" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: f87383d0f145b1b6cc8c7382f932bdbf6dd37f3f2526e1f17b73ee9f0bf9a6db8d7db04867712dd6f5839d5b967823ca3e534462335d8fd389b2bfda4aa0cb2e + languageName: node + linkType: hard + +"@graphql-codegen/typescript@npm:^3.0.4": + version: 3.0.4 + resolution: "@graphql-codegen/typescript@npm:3.0.4" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^4.2.0" + "@graphql-codegen/schema-ast": "npm:^3.0.1" + "@graphql-codegen/visitor-plugin-common": "npm:3.1.1" + auto-bind: "npm:~4.0.0" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 6fbf7cfda19fe8b02ab34a948c0d2cf58b68a26f8c31c03cbb097ef2196c1071d986bba6660d5da516c36c9f184e8bbef014cf851bf706aba81138a423cda250 + languageName: node + linkType: hard + +"@graphql-codegen/visitor-plugin-common@npm:2.13.1": + version: 2.13.1 + resolution: "@graphql-codegen/visitor-plugin-common@npm:2.13.1" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^2.7.2" + "@graphql-tools/optimize": "npm:^1.3.0" + "@graphql-tools/relay-operation-optimizer": "npm:^6.5.0" + "@graphql-tools/utils": "npm:^8.8.0" + auto-bind: "npm:~4.0.0" + change-case-all: "npm:1.0.14" + dependency-graph: "npm:^0.11.0" + graphql-tag: "npm:^2.11.0" + parse-filepath: "npm:^1.0.2" + tslib: "npm:~2.4.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 9dfc4893599721eba988103d4456345f915cab75c9a754e78a21bd7d05c49b00a01f38ffb70355d758626da0396ae3bb6d44fc98d5c8f9f36a1b122aea0063c4 + languageName: node + linkType: hard + +"@graphql-codegen/visitor-plugin-common@npm:3.1.1": + version: 3.1.1 + resolution: "@graphql-codegen/visitor-plugin-common@npm:3.1.1" + dependencies: + "@graphql-codegen/plugin-helpers": "npm:^4.2.0" + "@graphql-tools/optimize": "npm:^1.3.0" + "@graphql-tools/relay-operation-optimizer": "npm:^6.5.0" + "@graphql-tools/utils": "npm:^9.0.0" + auto-bind: "npm:~4.0.0" + change-case-all: "npm:1.0.15" + dependency-graph: "npm:^0.11.0" + graphql-tag: "npm:^2.11.0" + parse-filepath: "npm:^1.0.2" + tslib: "npm:~2.5.0" + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 4a393276f091de20cc3b8c3af07c772592328ed1c304835db533ab39dfeba4f7411040480404db21b677a85c055699cdd2992139a89456ec71492df6fa4ae9bf + languageName: node + linkType: hard + +"@graphql-inspector/core@npm:3.3.0": + version: 3.3.0 + resolution: "@graphql-inspector/core@npm:3.3.0" + dependencies: + dependency-graph: "npm:0.11.0" + object-inspect: "npm:1.10.3" + tslib: "npm:^2.0.0" + peerDependencies: + graphql: ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + checksum: 4a770985d66a389d00f7101d29bf91cb3e579ef2b2480c47fd6ecf48487131bd258c953e923996dc45e30dec84dccf0e031b1c16af7bd69203ab7220da21c860 + languageName: node + linkType: hard + +"@graphql-mesh/cache-localforage@npm:^0.93.1": + version: 0.93.1 + resolution: "@graphql-mesh/cache-localforage@npm:0.93.1" + dependencies: + localforage: "npm:1.10.0" + peerDependencies: + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + graphql: "*" + tslib: ^2.4.0 + checksum: aff34c39ebac62ea4c8a79e35e058beb791144b2da8d1ab7b225e8f24c3bd93fa80697c37c8b3caaaa036563a9b853e807c1d30fdc90eb4cca9000e3ad025384 + languageName: node + linkType: hard + +"@graphql-mesh/cli@npm:^0.82.33": + version: 0.82.35 + resolution: "@graphql-mesh/cli@npm:0.82.35" + dependencies: + "@graphql-codegen/core": "npm:^3.1.0" + "@graphql-codegen/typed-document-node": "npm:^4.0.1" + "@graphql-codegen/typescript": "npm:^3.0.4" + "@graphql-codegen/typescript-generic-sdk": "npm:^3.1.0" + "@graphql-codegen/typescript-operations": "npm:^3.0.4" + "@graphql-codegen/typescript-resolvers": "npm:^3.2.1" + "@graphql-mesh/config": "npm:^0.93.1" + "@graphql-mesh/cross-helpers": "npm:^0.3.4" + "@graphql-mesh/http": "npm:^0.93.1" + "@graphql-mesh/runtime": "npm:^0.93.1" + "@graphql-mesh/store": "npm:^0.93.1" + "@graphql-mesh/types": "npm:^0.93.1" + "@graphql-mesh/utils": "npm:^0.93.1" + "@graphql-tools/utils": "npm:^9.2.1" + ajv: "npm:^8.12.0" + change-case: "npm:^4.1.2" + cosmiconfig: "npm:^8.1.3" + dnscache: "npm:^1.0.2" + dotenv: "npm:^16.0.3" + graphql-import-node: "npm:^0.0.5" + graphql-ws: "npm:^5.12.1" + json-bigint-patch: "npm:^0.0.8" + json5: "npm:^2.2.3" + mkdirp: "npm:^3.0.0" + open: "npm:^7.4.2" + pascal-case: "npm:^3.1.2" + rimraf: "npm:^5.0.0" + ts-node: "npm:^10.9.1" + tsconfig-paths: "npm:^4.2.0" + tslib: "npm:^2.4.0" + typescript: "npm:^5.0.4" + ws: "npm:^8.13.0" + yargs: "npm:^17.7.1" + peerDependencies: + graphql: "*" + bin: + gql-mesh: cjs/bin.js + graphql-mesh: cjs/bin.js + graphql-mesh-esm: esm/bin.js + mesh: cjs/bin.js + checksum: 8d26fb52c8e295aeff376cac1b493e0a322899da7b8f4e8358bba50a7509dbb353c803b2926755faf3db69b0fb4531a2d1ab3df40a3ffc273be2032c08eb2cfa + languageName: node + linkType: hard + +"@graphql-mesh/config@npm:^0.93.1": + version: 0.93.1 + resolution: "@graphql-mesh/config@npm:0.93.1" + dependencies: + "@envelop/core": "npm:^3.0.6" + "@graphql-mesh/cache-localforage": "npm:^0.93.1" + "@graphql-mesh/merger-bare": "npm:^0.93.1" + "@graphql-mesh/merger-stitching": "npm:^0.93.1" + "@graphql-tools/code-file-loader": "npm:^7.3.22" + "@graphql-tools/graphql-file-loader": "npm:^7.5.17" + "@graphql-tools/load": "npm:^7.8.14" + "@whatwg-node/fetch": "npm:^0.8.3" + camel-case: "npm:^4.1.2" + param-case: "npm:^3.0.4" + pascal-case: "npm:^3.1.2" + peerDependencies: + "@graphql-mesh/cross-helpers": ^0.3.4 + "@graphql-mesh/runtime": ^0.93.1 + "@graphql-mesh/store": ^0.93.1 + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: 76eb81e5095f3ed08501c635da4e96ade693d0669f26c9a9c1f2d612e7cacf6cdfb6f6fea264a1010d4dcfc91c7cdfd8b0567d1db4f9f4b704fc740ef71fec37 + languageName: node + linkType: hard + +"@graphql-mesh/cross-helpers@npm:^0.3.4": + version: 0.3.4 + resolution: "@graphql-mesh/cross-helpers@npm:0.3.4" + dependencies: + path-browserify: "npm:1.0.1" + react-native-fs: "npm:2.20.0" + react-native-path: "npm:0.0.5" + peerDependencies: + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + checksum: ae9b067312242c9d5fd9e554e4c2314b200e6ca4c07894fe27b20f0b070acbe08658d2afbfcde7ac9853aab9583c6aa6c80dfe7fdd1fd1ee05257f43ebce76b1 + languageName: node + linkType: hard + +"@graphql-mesh/graphql@npm:^0.93.0": + version: 0.93.1 + resolution: "@graphql-mesh/graphql@npm:0.93.1" + dependencies: + "@graphql-mesh/string-interpolation": "npm:^0.4.4" + "@graphql-tools/delegate": "npm:^9.0.32" + "@graphql-tools/url-loader": "npm:^7.17.18" + "@graphql-tools/wrap": "npm:^9.4.2" + lodash.get: "npm:^4.4.2" + peerDependencies: + "@graphql-mesh/cross-helpers": ^0.3.4 + "@graphql-mesh/store": ^0.93.1 + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: a2bbe8fa602d4f0dcff5c5a02fe087f1679919c32cc6f2a05a79be5819f36ea29134ce6d20ccf17f37f0d1c3f428d5071b392ce0a001226e1a81cb72427a8eba + languageName: node + linkType: hard + +"@graphql-mesh/http@npm:^0.93.1": + version: 0.93.2 + resolution: "@graphql-mesh/http@npm:0.93.2" + dependencies: + fets: "npm:^0.1.1" + graphql-yoga: "npm:^3.9.1" + peerDependencies: + "@graphql-mesh/cross-helpers": ^0.3.4 + "@graphql-mesh/runtime": ^0.93.2 + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + graphql: "*" + tslib: ^2.4.0 + checksum: b943d4b87aad1f4c77abe9aabbf3ab6519215327c9daaf81f099970596f87fb1dc5f2dbcf6a3147de3a1645d6c777ec1a0acebd97daf3002b6560acf79297985 + languageName: node + linkType: hard + +"@graphql-mesh/merger-bare@npm:^0.93.1": + version: 0.93.1 + resolution: "@graphql-mesh/merger-bare@npm:0.93.1" + dependencies: + "@graphql-mesh/merger-stitching": "npm:0.93.1" + "@graphql-tools/schema": "npm:9.0.19" + peerDependencies: + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: a7530d11dbed7fa27e270c92b1c08c5198adc47f1c843571912851ac20c28230e00006b15c45f697d86d9e3d8da1c928c0afce2253894a71a374ee2c4163b57b + languageName: node + linkType: hard + +"@graphql-mesh/merger-stitching@npm:0.93.1, @graphql-mesh/merger-stitching@npm:^0.93.1": + version: 0.93.1 + resolution: "@graphql-mesh/merger-stitching@npm:0.93.1" + dependencies: + "@graphql-tools/delegate": "npm:^9.0.32" + "@graphql-tools/schema": "npm:^9.0.18" + "@graphql-tools/stitch": "npm:^8.7.48" + "@graphql-tools/stitching-directives": "npm:^2.3.34" + peerDependencies: + "@graphql-mesh/store": ^0.93.1 + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: ca99c35abfcec0f480fdcd973e2ce489e61cb48f7b0357a1214d6a768dcf758c3acfaffadd6eb2bc1be62cf60f1e6f9496fb7898638c6204fead83bafde8699d + languageName: node + linkType: hard + +"@graphql-mesh/runtime@npm:^0.93.1": + version: 0.93.2 + resolution: "@graphql-mesh/runtime@npm:0.93.2" + dependencies: + "@envelop/core": "npm:^3.0.6" + "@envelop/extended-validation": "npm:^2.0.6" + "@graphql-mesh/string-interpolation": "npm:^0.4.4" + "@graphql-tools/batch-delegate": "npm:^8.4.25" + "@graphql-tools/batch-execute": "npm:^8.5.19" + "@graphql-tools/delegate": "npm:^9.0.32" + "@graphql-tools/wrap": "npm:^9.4.2" + "@whatwg-node/fetch": "npm:^0.8.3" + peerDependencies: + "@graphql-mesh/cross-helpers": ^0.3.4 + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: d07f2756e8e39f989f4d5beade8156a84d0d5ca862eceb4f778f5e689afbc1b15ba42a3f9040208d2e97753cbf1a31186cfcba9c35e78f2b2251bbbfd48e6bab + languageName: node + linkType: hard + +"@graphql-mesh/store@npm:^0.93.1": + version: 0.93.1 + resolution: "@graphql-mesh/store@npm:0.93.1" + dependencies: + "@graphql-inspector/core": "npm:3.3.0" + peerDependencies: + "@graphql-mesh/cross-helpers": ^0.3.4 + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: 4578530d418f0d96f90455836b773863affac2fd8de17417c9dc08f47524d30a6c2e287c9e03159e2d5d526cc4e42498d7edc346325d98efd9c06359ca470076 + languageName: node + linkType: hard + +"@graphql-mesh/string-interpolation@npm:^0.4.4": + version: 0.4.4 + resolution: "@graphql-mesh/string-interpolation@npm:0.4.4" + dependencies: + dayjs: "npm:1.11.7" + json-pointer: "npm:0.6.2" + lodash.get: "npm:4.4.2" + peerDependencies: + graphql: "*" + tslib: ^2.4.0 + checksum: 5c39c1e5955b0de3048f55c29f26a20fbf25e595b02c6fb157d0fff75198277a960947bb2768f2ab94444cc590e796f264093a0d12c03759ed037b8febf7c558 + languageName: node + linkType: hard + +"@graphql-mesh/transform-type-merging@npm:^0.93.0": + version: 0.93.1 + resolution: "@graphql-mesh/transform-type-merging@npm:0.93.1" + dependencies: + "@graphql-tools/delegate": "npm:^9.0.32" + "@graphql-tools/stitching-directives": "npm:^2.3.34" + peerDependencies: + "@graphql-mesh/types": ^0.93.1 + "@graphql-mesh/utils": ^0.93.1 + graphql: "*" + tslib: ^2.4.0 + checksum: e57855f091267898783dc195dff16c9d0ac8e0c3dc4cbfff0e3f622d137dd45f3f982c92c5f74c3445fd5683b54ee762e25ac7a576393c363c99b83f33099b18 + languageName: node + linkType: hard + +"@graphql-mesh/types@npm:^0.93.1": + version: 0.93.2 + resolution: "@graphql-mesh/types@npm:0.93.2" + dependencies: + "@graphql-tools/batch-delegate": "npm:^8.4.25" + "@graphql-tools/delegate": "npm:^9.0.32" + "@graphql-typed-document-node/core": "npm:^3.2.0" + peerDependencies: + "@graphql-mesh/store": ^0.93.1 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: 4f8494cb84f0412c9ac6272ea4374e55b7ce722bc4037389118b080362533985c16f4bdd7ca558439949c1cf3b13e754c8dfdbd350aa8ceb37fc5af939b9a7a0 + languageName: node + linkType: hard + +"@graphql-mesh/utils@npm:^0.93.1": + version: 0.93.2 + resolution: "@graphql-mesh/utils@npm:0.93.2" + dependencies: + "@graphql-mesh/string-interpolation": "npm:^0.4.4" + "@graphql-tools/delegate": "npm:^9.0.32" + dset: "npm:^3.1.2" + js-yaml: "npm:^4.1.0" + lodash.get: "npm:^4.4.2" + lodash.topath: "npm:^4.5.2" + tiny-lru: "npm:^8.0.2" + peerDependencies: + "@graphql-mesh/cross-helpers": ^0.3.4 + "@graphql-mesh/types": ^0.93.2 + "@graphql-tools/utils": ^9.2.1 + graphql: "*" + tslib: ^2.4.0 + checksum: 13752b9baf563e367a7c88362686b0abbe8b9e59ec20e91aa0081232466a9765988e6e130cd5aed56909c890a7be7ca0957b8aa654f0d90a58e4aee3f290ebb0 + languageName: node + linkType: hard + +"@graphql-tools/batch-delegate@npm:^8.4.25, @graphql-tools/batch-delegate@npm:^8.4.27": + version: 8.4.27 + resolution: "@graphql-tools/batch-delegate@npm:8.4.27" + dependencies: + "@graphql-tools/delegate": "npm:^9.0.35" + "@graphql-tools/utils": "npm:^9.2.1" + dataloader: "npm:2.2.2" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 86e840667f707d87dd5932d918b1df72d0df43d9edff76486ab1eb5ca9ba875d8bce66816abf42a67b91168dbd76efa6337323efbd510eaa564a7b2e7e4e6580 + languageName: node + linkType: hard + +"@graphql-tools/batch-execute@npm:^8.5.19, @graphql-tools/batch-execute@npm:^8.5.22": + version: 8.5.22 + resolution: "@graphql-tools/batch-execute@npm:8.5.22" + dependencies: + "@graphql-tools/utils": "npm:^9.2.1" + dataloader: "npm:^2.2.2" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: ff5ad8f36844cfa823061e6aa4cb0e5c4e2ebbd716c02c04bc1fdf637799fea760abd9f53083e9ebb038a0aa61263cf6360535776610dbfb9b0981e1deb1fb8a + languageName: node + linkType: hard + +"@graphql-tools/code-file-loader@npm:^7.3.22": + version: 7.3.23 + resolution: "@graphql-tools/code-file-loader@npm:7.3.23" + dependencies: + "@graphql-tools/graphql-tag-pluck": "npm:7.5.2" + "@graphql-tools/utils": "npm:^9.2.1" + globby: "npm:^11.0.3" + tslib: "npm:^2.4.0" + unixify: "npm:^1.0.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: c7a59c9422c20b3deecdaa227a73c900581487f3f13dc4105ffe2e32f4d740b9d9409d4aed2a8f8c78f659f5181f93a20cfbb963994c9902261a1df7486c9bd4 + languageName: node + linkType: hard + +"@graphql-tools/delegate@npm:^9.0.31, @graphql-tools/delegate@npm:^9.0.32, @graphql-tools/delegate@npm:^9.0.35": + version: 9.0.35 + resolution: "@graphql-tools/delegate@npm:9.0.35" + dependencies: + "@graphql-tools/batch-execute": "npm:^8.5.22" + "@graphql-tools/executor": "npm:^0.0.20" + "@graphql-tools/schema": "npm:^9.0.19" + "@graphql-tools/utils": "npm:^9.2.1" + dataloader: "npm:^2.2.2" + tslib: "npm:^2.5.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 1199ad14ffa1f0e8d6b12102bd78f7b0451ebe802f4bb7b4332a6fc27acf26b5d092b9dc6d656c7595efb0f7fc3bc247ba7fe1bb5317892443f42b27af4c54fc + languageName: node linkType: hard -"@graphprotocol/common-ts@npm:^1.8.3": - version: 1.8.7 - resolution: "@graphprotocol/common-ts@npm:1.8.7" +"@graphql-tools/executor-graphql-ws@npm:^0.0.14": + version: 0.0.14 + resolution: "@graphql-tools/executor-graphql-ws@npm:0.0.14" dependencies: - "@graphprotocol/contracts": "npm:2.1.0" - "@graphprotocol/pino-sentry-simple": "npm:0.7.1" - "@urql/core": "npm:2.4.4" - "@urql/exchange-execute": "npm:1.2.2" - body-parser: "npm:1.19.1" - bs58: "npm:4.0.1" - cors: "npm:2.8.5" - cross-fetch: "npm:3.1.5" - ethers: "npm:5.6.2" - express: "npm:4.17.3" - graphql: "npm:16.3.0" - graphql-tag: "npm:2.12.6" - helmet: "npm:5.0.2" - morgan: "npm:1.10.0" - ngeohash: "npm:0.6.3" - pg: "npm:8.7.3" - pg-hstore: "npm:2.3.4" - pino: "npm:7.6.0" - pino-multi-stream: "npm:6.0.0" - prom-client: "npm:14.0.1" - sequelize: "npm:6.19.0" - checksum: 64a974245e47bc0937ee1e7905886530786ae61fcea4e1566193466446c1bc0a18f7a7570826a1defb6c05edddb7b82f3da7a33ab5e2ce4df90340eb5d78a0ce + "@graphql-tools/utils": "npm:^9.2.1" + "@repeaterjs/repeater": "npm:3.0.4" + "@types/ws": "npm:^8.0.0" + graphql-ws: "npm:5.12.1" + isomorphic-ws: "npm:5.0.0" + tslib: "npm:^2.4.0" + ws: "npm:8.13.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 35619da6da45320ea53433018c4e2aa3ceab5fed097b9b51b6151007817139c9cb9f554d44a6fc51185d3ba829824cad9758f6cd98ead052a75d3d757306400f languageName: node linkType: hard -"@graphprotocol/common-ts@npm:^2.0.7": - version: 2.0.9 - resolution: "@graphprotocol/common-ts@npm:2.0.9" +"@graphql-tools/executor-http@npm:^0.1.7": + version: 0.1.10 + resolution: "@graphql-tools/executor-http@npm:0.1.10" + dependencies: + "@graphql-tools/utils": "npm:^9.2.1" + "@repeaterjs/repeater": "npm:^3.0.4" + "@whatwg-node/fetch": "npm:^0.8.1" + dset: "npm:^3.1.2" + extract-files: "npm:^11.0.0" + meros: "npm:^1.2.1" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: db2bb80e10bde0e6e34c3c86ed30c4f3082ba332fba5700d182045c4eb40453e670ea2277426fea31167481ed0b89446644ff106848e397b83e17c61d73218f3 + languageName: node + linkType: hard + +"@graphql-tools/executor-legacy-ws@npm:^0.0.11": + version: 0.0.11 + resolution: "@graphql-tools/executor-legacy-ws@npm:0.0.11" dependencies: - "@graphprotocol/contracts": "npm:5.3.3" - "@graphprotocol/pino-sentry-simple": "npm:0.7.1" - "@urql/core": "npm:2.4.4" - "@urql/exchange-execute": "npm:1.2.2" - body-parser: "npm:1.20.2" - bs58: "npm:5.0.0" - cors: "npm:2.8.5" - cross-fetch: "npm:4.0.0" - ethers: "npm:5.7.0" - express: "npm:4.18.2" - graphql: "npm:16.8.0" - graphql-tag: "npm:2.12.6" - helmet: "npm:7.0.0" - morgan: "npm:1.10.0" - ngeohash: "npm:0.6.3" - pg: "npm:8.11.3" - pg-hstore: "npm:2.3.4" - pino: "npm:7.6.0" - pino-multi-stream: "npm:6.0.0" - prom-client: "npm:14.2.0" - sequelize: "npm:6.33.0" - checksum: b0009fbfcd0eb86f411627ef4cb974b1cee33922610f7636833e4b56cb9ca5652161115072e880b06e2ab500c34068d3d2f193395d0b16f69a5562d2b7585c74 + "@graphql-tools/utils": "npm:^9.2.1" + "@types/ws": "npm:^8.0.0" + isomorphic-ws: "npm:5.0.0" + tslib: "npm:^2.4.0" + ws: "npm:8.13.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: caf03080b125a9c3291a09a19747ffd7d16c99bfa378ee26bbd82d7613efcaa516d684ed74139a70267c68d8b4ff071541a4db4c9a3e9d2ea944d2bf912b6f50 languageName: node linkType: hard -"@graphprotocol/contracts-monorepo@workspace:.": - version: 0.0.0-use.local - resolution: "@graphprotocol/contracts-monorepo@workspace:." +"@graphql-tools/executor@npm:^0.0.18": + version: 0.0.18 + resolution: "@graphql-tools/executor@npm:0.0.18" dependencies: - "@commitlint/cli": "npm:^18.4.3" - "@commitlint/config-conventional": "npm:^18.4.3" - husky: "npm:^8.0.3" - languageName: unknown - linkType: soft + "@graphql-tools/utils": "npm:^9.2.1" + "@graphql-typed-document-node/core": "npm:3.2.0" + "@repeaterjs/repeater": "npm:3.0.4" + tslib: "npm:^2.4.0" + value-or-promise: "npm:1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: f3eb05d17a25f1b8e405fc473d394d0d4e8fa8533bbeb47915a2e714b60b3bd4eb34dcbb60fc631729842e05a628191ff209e57cf3ebc450289547757511de40 + languageName: node + linkType: hard -"@graphprotocol/contracts@npm:2.1.0": - version: 2.1.0 - resolution: "@graphprotocol/contracts@npm:2.1.0" +"@graphql-tools/executor@npm:^0.0.20": + version: 0.0.20 + resolution: "@graphql-tools/executor@npm:0.0.20" dependencies: - console-table-printer: "npm:^2.11.1" - ethers: "npm:^5.6.0" - checksum: 948c7f667b9e7efb83b06e06fd7218d044b8a1c8fed37a555f784d9ef2ef6c840306d64163dd1d82657d61d2edb563eff35af9b96bb2ef9e76ea59a6b46b6282 + "@graphql-tools/utils": "npm:^9.2.1" + "@graphql-typed-document-node/core": "npm:3.2.0" + "@repeaterjs/repeater": "npm:^3.0.4" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: c9300ac118040ea1da18f4cc79613292d91b6e5edc312763c5b8a9da79cc3581bc7d43a292120c7b4c71367613c4b21da3e656985dce827fae0503a5fcbcbc71 languageName: node linkType: hard -"@graphprotocol/contracts@npm:5.3.3": - version: 5.3.3 - resolution: "@graphprotocol/contracts@npm:5.3.3" +"@graphql-tools/graphql-file-loader@npm:^7.5.17": + version: 7.5.17 + resolution: "@graphql-tools/graphql-file-loader@npm:7.5.17" dependencies: - console-table-printer: "npm:^2.11.1" - ethers: "npm:^5.6.0" - checksum: 00d5fd682e829da8747eaebc65645b660e7551234fbd8a05f72b7b75ce6537dbfe51e410d84eeaa4dfe7dc87c16c276b50c30fcb6d528c83fa42698acc306af3 + "@graphql-tools/import": "npm:6.7.18" + "@graphql-tools/utils": "npm:^9.2.1" + globby: "npm:^11.0.3" + tslib: "npm:^2.4.0" + unixify: "npm:^1.0.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: f737f14357731ad01da57755e1cf26ce375b475209d6ab7e4b656b56191a8979d2ab7dd5d1c54a1f11e04374f7a373fa95ea5ec6a001d0cef913ea208fadc65b languageName: node linkType: hard -"@graphprotocol/contracts@workspace:^6.0.0, @graphprotocol/contracts@workspace:packages/contracts": - version: 0.0.0-use.local - resolution: "@graphprotocol/contracts@workspace:packages/contracts" +"@graphql-tools/graphql-tag-pluck@npm:7.5.2": + version: 7.5.2 + resolution: "@graphql-tools/graphql-tag-pluck@npm:7.5.2" dependencies: - "@arbitrum/sdk": "npm:^3.0.0" - "@defi-wonderland/smock": "npm:^2.0.7" - "@ethersproject/experimental": "npm:^5.6.0" - "@graphprotocol/common-ts": "npm:^1.8.3" - "@graphprotocol/sdk": "workspace:^0.3.0" - "@nomiclabs/hardhat-ethers": "npm:^2.2.3" - "@nomiclabs/hardhat-etherscan": "npm:^3.1.7" - "@nomiclabs/hardhat-waffle": "npm:2.0.3" - "@openzeppelin/contracts": "npm:^3.4.1" - "@openzeppelin/contracts-upgradeable": "npm:3.4.2" - "@openzeppelin/hardhat-defender": "npm:^1.8.1" - "@openzeppelin/hardhat-upgrades": "npm:^1.6.0" - "@tenderly/hardhat-tenderly": "npm:1.0.13" - "@typechain/ethers-v5": "npm:^7.0.0" - "@typechain/hardhat": "npm:^2.0.0" - "@types/bs58": "npm:^4.0.1" - "@types/chai-as-promised": "npm:^7.1.5" - "@types/dotenv": "npm:^8.2.0" - "@types/glob": "npm:^7.2.0" - "@types/inquirer": "npm:^7.3.1" - "@types/minimist": "npm:^1.2.1" - "@types/mocha": "npm:^8.2.2" - "@types/node": "npm:^20.9.0" - "@types/sinon-chai": "npm:^3.2.12" - "@types/winston": "npm:^2.4.4" - "@types/yargs": "npm:^16.0.0" - "@typescript-eslint/eslint-plugin": "npm:^4.0.0" - "@typescript-eslint/parser": "npm:^4.0.0" - "@urql/core": "npm:^2.1.3" - arbos-precompiles: "npm:^1.0.2" - bignumber.js: "npm:^9.0.0" - chai: "npm:^4.3.4" - chai-as-promised: "npm:^7.1.1" - cli-table: "npm:^0.3.6" - console-table-printer: "npm:^2.11.1" - dotenv: "npm:^9.0.0" - eslint: "npm:^7.24.0" - eslint-config-prettier: "npm:^8.3.0" - eslint-plugin-no-only-tests: "npm:^2.4.0" - eslint-plugin-prettier: "npm:^3.4.0" - ethereum-waffle: "npm:^3.2.0" - ethers: "npm:^5.7.2" - form-data: "npm:^4.0.0" - glob: "npm:^8.0.3" - graphql-tag: "npm:^2.12.4" - hardhat: "npm:~2.14.0" - hardhat-abi-exporter: "npm:^2.2.0" - hardhat-contract-sizer: "npm:^2.0.3" - hardhat-gas-reporter: "npm:^1.0.4" - hardhat-secure-accounts: "npm:0.0.5" - hardhat-storage-layout: "npm:0.1.6" - hardhat-tracer: "npm:^1.0.0-alpha.6" - inquirer: "npm:^8.0.0" - ipfs-http-client: "npm:47.0.1" - isomorphic-fetch: "npm:^3.0.0" - lint-staged: "npm:^10.5.4" - p-queue: "npm:^6.6.1" - prettier: "npm:^2.2.1" - prettier-plugin-solidity: "npm:1.0.0-beta.19" - solhint: "npm:^3.3.6" - solhint-plugin-prettier: "npm:^0.0.5" - solidity-coverage: "npm:^0.7.16" - ts-node: "npm:^10.9.1" - typechain: "npm:^5.0.0" - typescript: "npm:^4.7.4" - winston: "npm:^3.3.3" - yaml: "npm:^1.10.2" - yargs: "npm:^17.0.0" - languageName: unknown - linkType: soft + "@babel/parser": "npm:^7.16.8" + "@babel/plugin-syntax-import-assertions": "npm:^7.20.0" + "@babel/traverse": "npm:^7.16.8" + "@babel/types": "npm:^7.16.8" + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 86d9558cdd64526dd8ff8c3fdcb8c242c00911fac856ea7c8d6e437a13a1ee38aea44a55c586bcba13481928f45cd3e2006712cc750a8ba5a3d43e7be6097ea8 + languageName: node + linkType: hard -"@graphprotocol/pino-sentry-simple@npm:0.7.1": - version: 0.7.1 - resolution: "@graphprotocol/pino-sentry-simple@npm:0.7.1" +"@graphql-tools/import@npm:6.7.18": + version: 6.7.18 + resolution: "@graphql-tools/import@npm:6.7.18" dependencies: - "@sentry/node": "npm:^5.21.1" - pumpify: "npm:^2.0.1" - split2: "npm:^3.1.1" - through2: "npm:^3.0.1" - checksum: 4aad42ecc41ebc7a447f03e351ce10034619da119f1d427231f7abc329050bbe34b44d88f92c0e7f41e879541bc747c1814b3fe3a32d3b8fdafb7acfc7635202 + "@graphql-tools/utils": "npm:^9.2.1" + resolve-from: "npm:5.0.0" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: d33e37a1879dd43ac2851c9bac2f2873c58bb3687f1c06e159760dbb5e540ef074d688df70cc6dbd3ee5de48d437878df8f65a7c65ae80bd025bf98f2d615732 languageName: node linkType: hard -"@graphprotocol/sdk@workspace:^0.3.0, @graphprotocol/sdk@workspace:packages/sdk": - version: 0.0.0-use.local - resolution: "@graphprotocol/sdk@workspace:packages/sdk" +"@graphql-tools/load@npm:^7.8.14": + version: 7.8.14 + resolution: "@graphql-tools/load@npm:7.8.14" dependencies: - "@arbitrum/sdk": "npm:^3.1.12" - "@ethersproject/experimental": "npm:^5.7.0" - "@graphprotocol/common-ts": "npm:^2.0.7" - "@graphprotocol/contracts": "workspace:^6.0.0" - "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.9" - "@nomiclabs/hardhat-ethers": "npm:^2.2.3" - "@types/chai": "npm:^4.3.9" - "@types/chai-as-promised": "npm:^7.1.7" - "@types/debug": "npm:^4.1.10" - "@types/inquirer": "npm:^8.0.0" - "@types/lodash": "npm:^4.14.200" - "@types/mocha": "npm:^10.0.3" - "@types/node": "npm:^20.8.7" - "@typescript-eslint/eslint-plugin": "npm:^6.8.0" - "@typescript-eslint/parser": "npm:^6.8.0" - chai: "npm:^4.3.10" - chai-as-promised: "npm:^7.1.1" - debug: "npm:^4.3.4" - eslint: "npm:^8.52.0" - eslint-config-prettier: "npm:^9.0.0" - eslint-plugin-no-only-tests: "npm:^3.1.0" - eslint-plugin-prettier: "npm:^5.0.1" - ethers: "npm:^5.7.0" - hardhat: "npm:~2.14.0" - hardhat-secure-accounts: "npm:^0.0.6" - inquirer: "npm:^8.0.0" - lodash: "npm:^4.17.21" - prettier: "npm:^3.0.3" - ts-node: "npm:^10.9.1" - typescript: "npm:^5.1.6" - yaml: "npm:^1.10.2" - languageName: unknown - linkType: soft + "@graphql-tools/schema": "npm:^9.0.18" + "@graphql-tools/utils": "npm:^9.2.1" + p-limit: "npm:3.1.0" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 1fa036ac596ccf48f350aa545d108c173184d9b53247f9e21c0d4ba96c5cba4a0b44281f9154f122e1e8e9d9d6eab93a5b2618ca8a797969bde1e75c1d45e786 + languageName: node + linkType: hard + +"@graphql-tools/merge@npm:^8.4.1, @graphql-tools/merge@npm:^8.4.2": + version: 8.4.2 + resolution: "@graphql-tools/merge@npm:8.4.2" + dependencies: + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 2df55222b48e010e683572f456cf265aabae5748c59f7c1260c66dec9794b7a076d3706f04da969b77f0a32c7ccb4551fee30125931d3fe9c98a8806aae9a3f4 + languageName: node + linkType: hard + +"@graphql-tools/optimize@npm:^1.3.0": + version: 1.4.0 + resolution: "@graphql-tools/optimize@npm:1.4.0" + dependencies: + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 10be773b0082fe54b9505469a89925f1a5e33f866453b88cd411261951e8718f8720451e07c56cbfb762970b56b9b45c7c748d62afcdcf9414ec64533e94e543 + languageName: node + linkType: hard + +"@graphql-tools/relay-operation-optimizer@npm:^6.5.0": + version: 6.5.18 + resolution: "@graphql-tools/relay-operation-optimizer@npm:6.5.18" + dependencies: + "@ardatan/relay-compiler": "npm:12.0.0" + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 9d74d65da8bf474e256ff0cfb77afb442a968451ded6a92b8348d8ac1bca3b2c13a578ab29ac869d10d53e0101219fe8283d485fff920aa7abcc68fcbbdd9a36 + languageName: node + linkType: hard + +"@graphql-tools/schema@npm:9.0.19, @graphql-tools/schema@npm:^9.0.0, @graphql-tools/schema@npm:^9.0.18, @graphql-tools/schema@npm:^9.0.19": + version: 9.0.19 + resolution: "@graphql-tools/schema@npm:9.0.19" + dependencies: + "@graphql-tools/merge": "npm:^8.4.1" + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 42fd8ca8d3c8d60b583077c201980518482ff0cd5ed0c1f14bd9b835a2689ad41d02cbd3478f7d7dea7aec1227f7639fd5deb5e6360852a2e542b96b44bfb7a4 + languageName: node + linkType: hard + +"@graphql-tools/stitch@npm:^8.7.48": + version: 8.7.50 + resolution: "@graphql-tools/stitch@npm:8.7.50" + dependencies: + "@graphql-tools/batch-delegate": "npm:^8.4.27" + "@graphql-tools/delegate": "npm:^9.0.35" + "@graphql-tools/executor": "npm:^0.0.20" + "@graphql-tools/merge": "npm:^8.4.2" + "@graphql-tools/schema": "npm:^9.0.18" + "@graphql-tools/utils": "npm:^9.2.1" + "@graphql-tools/wrap": "npm:^9.4.2" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.11" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 806b9a9d6ef66d86bf85241ad3d7dd9c0c4c7af98d4a1ba56f048a2525946f3197f00e7b173741c258389be751fb698c28c9fbca521eea47d8b3df7e29a2b171 + languageName: node + linkType: hard + +"@graphql-tools/stitching-directives@npm:^2.3.34": + version: 2.3.34 + resolution: "@graphql-tools/stitching-directives@npm:2.3.34" + dependencies: + "@graphql-tools/delegate": "npm:^9.0.31" + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: d24a9a6606f7fd551c6b597e0a2a6c22ab9235aacda1339bb6406720875b674dd32b409989c9767cb1e8fe6249fc3f8f9a3f35ad4482ec911f387b2bd819ad18 + languageName: node + linkType: hard + +"@graphql-tools/url-loader@npm:^7.17.18": + version: 7.17.18 + resolution: "@graphql-tools/url-loader@npm:7.17.18" + dependencies: + "@ardatan/sync-fetch": "npm:^0.0.1" + "@graphql-tools/delegate": "npm:^9.0.31" + "@graphql-tools/executor-graphql-ws": "npm:^0.0.14" + "@graphql-tools/executor-http": "npm:^0.1.7" + "@graphql-tools/executor-legacy-ws": "npm:^0.0.11" + "@graphql-tools/utils": "npm:^9.2.1" + "@graphql-tools/wrap": "npm:^9.4.2" + "@types/ws": "npm:^8.0.0" + "@whatwg-node/fetch": "npm:^0.8.0" + isomorphic-ws: "npm:^5.0.0" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.11" + ws: "npm:^8.12.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 963153fde3389f3e44de63c8bca3ce43c85c6ef0f9c5feb56b24d9146f4bf4fef84bebe44a961acc0e0aa0a48081add24684404b83b84bbb9f5e3fcdbc131cae + languageName: node + linkType: hard + +"@graphql-tools/utils@npm:^8.8.0": + version: 8.13.1 + resolution: "@graphql-tools/utils@npm:8.13.1" + dependencies: + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: f9bab1370aa91e706abec4c8ea980e15293cb78bd4effba53ad2365dc39d81148db7667b3ef89b35f0a0b0ad58081ffdac4264b7125c69fa8393590ae5025745 + languageName: node + linkType: hard + +"@graphql-tools/utils@npm:^9.0.0, @graphql-tools/utils@npm:^9.1.1, @graphql-tools/utils@npm:^9.2.1": + version: 9.2.1 + resolution: "@graphql-tools/utils@npm:9.2.1" + dependencies: + "@graphql-typed-document-node/core": "npm:^3.1.1" + tslib: "npm:^2.4.0" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 37a7bd7e14d28ff1bacc007dca84bc6cef2d7d7af9a547b5dbe52fcd134afddd6d4a7b2148cfbaff5ddba91a868453d597da77bd0457fb0be15928f916901606 + languageName: node + linkType: hard + +"@graphql-tools/wrap@npm:^9.4.2": + version: 9.4.2 + resolution: "@graphql-tools/wrap@npm:9.4.2" + dependencies: + "@graphql-tools/delegate": "npm:^9.0.31" + "@graphql-tools/schema": "npm:^9.0.18" + "@graphql-tools/utils": "npm:^9.2.1" + tslib: "npm:^2.4.0" + value-or-promise: "npm:^1.0.12" + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + checksum: 6b0aa1a78af8280c7356e2841156a6708a9a147e5991afae9586046ef000b8d08e6d0405dceb10ffbfb0c208a97a527a16d5f04ee2fbf99f6eefe98fe6037292 + languageName: node + linkType: hard -"@graphql-typed-document-node/core@npm:^3.1.1": +"@graphql-typed-document-node/core@npm:3.2.0, @graphql-typed-document-node/core@npm:^3.1.1, @graphql-typed-document-node/core@npm:^3.2.0": version: 3.2.0 resolution: "@graphql-typed-document-node/core@npm:3.2.0" peerDependencies: @@ -1724,25 +3619,45 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.11.13": - version: 0.11.13 - resolution: "@humanwhocodes/config-array@npm:0.11.13" +"@graphql-yoga/logger@npm:^0.0.1": + version: 0.0.1 + resolution: "@graphql-yoga/logger@npm:0.0.1" dependencies: - "@humanwhocodes/object-schema": "npm:^2.0.1" - debug: "npm:^4.1.1" - minimatch: "npm:^3.0.5" - checksum: d76ca802d853366094d0e98ff0d0994117fc8eff96649cd357b15e469e428228f597cd2e929d54ab089051684949955f16ee905bb19f7b2f0446fb377157be7a + tslib: "npm:^2.3.1" + checksum: 9d786cf0de21230310874d29987695b510749f0ff3a92ded3565e837e9d141588ac8fc8669a3ab235ec0dffe4ffe920e7546004858c7d06af8ee85bdd4d09c05 languageName: node linkType: hard -"@humanwhocodes/config-array@npm:^0.5.0": - version: 0.5.0 - resolution: "@humanwhocodes/config-array@npm:0.5.0" +"@graphql-yoga/subscription@npm:^3.1.0": + version: 3.1.0 + resolution: "@graphql-yoga/subscription@npm:3.1.0" dependencies: - "@humanwhocodes/object-schema": "npm:^1.2.0" - debug: "npm:^4.1.1" - minimatch: "npm:^3.0.4" - checksum: 217fac9e03492361825a2bf761d4bb7ec6d10002a10f7314142245eb13ac9d123523d24d5619c3c4159af215c7b3e583ed386108e227014bef4efbf9caca8ccc + "@graphql-yoga/typed-event-target": "npm:^1.0.0" + "@repeaterjs/repeater": "npm:^3.0.4" + "@whatwg-node/events": "npm:0.0.2" + tslib: "npm:^2.3.1" + checksum: 03f112b615ebc2ccd538bbbb7ac0362ffee79b23c5f5cffedb7f0a4b5bfbcc661e528a366b987fafef3193de22f828b4f76338fb5798e87fbb41955fef8070c1 + languageName: node + linkType: hard + +"@graphql-yoga/typed-event-target@npm:^1.0.0": + version: 1.0.0 + resolution: "@graphql-yoga/typed-event-target@npm:1.0.0" + dependencies: + "@repeaterjs/repeater": "npm:^3.0.4" + tslib: "npm:^2.3.1" + checksum: baf9115148db27e05b06d8394f9a4344bc66c41cc389d529d7cd5eb5100b21bab973635ae2e497c329e14305d5d9a68c9c700ad63afaa7c9642814582b3e28a3 + languageName: node + linkType: hard + +"@humanwhocodes/config-array@npm:^0.11.13, @humanwhocodes/config-array@npm:^0.11.14": + version: 0.11.14 + resolution: "@humanwhocodes/config-array@npm:0.11.14" + dependencies: + "@humanwhocodes/object-schema": "npm:^2.0.2" + debug: "npm:^4.3.1" + minimatch: "npm:^3.0.5" + checksum: 66f725b4ee5fdd8322c737cb5013e19fac72d4d69c8bf4b7feb192fcb83442b035b92186f8e9497c220e58b2d51a080f28a73f7899bc1ab288c3be172c467541 languageName: node linkType: hard @@ -1753,17 +3668,10 @@ __metadata: languageName: node linkType: hard -"@humanwhocodes/object-schema@npm:^1.2.0": - version: 1.2.1 - resolution: "@humanwhocodes/object-schema@npm:1.2.1" - checksum: c3c35fdb70c04a569278351c75553e293ae339684ed75895edc79facc7276e351115786946658d78133130c0cca80e57e2203bc07f8fa7fe7980300e8deef7db - languageName: node - linkType: hard - -"@humanwhocodes/object-schema@npm:^2.0.1": - version: 2.0.1 - resolution: "@humanwhocodes/object-schema@npm:2.0.1" - checksum: 9dba24e59fdb4041829d92b693aacb778add3b6f612aaa9c0774f3b650c11a378cc64f042a59da85c11dae33df456580a3c36837b953541aed6ff94294f97fac +"@humanwhocodes/object-schema@npm:^2.0.2": + version: 2.0.2 + resolution: "@humanwhocodes/object-schema@npm:2.0.2" + checksum: 6fd83dc320231d71c4541d0244051df61f301817e9f9da9fd4cb7e44ec8aacbde5958c1665b0c419401ab935114fdf532a6ad5d4e7294b1af2f347dd91a6983f languageName: node linkType: hard @@ -1781,14 +3689,32 @@ __metadata: languageName: node linkType: hard -"@jridgewell/resolve-uri@npm:^3.0.3": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: 0dbc9e29bc640bbbdc5b9876d2859c69042bfcf1423c1e6421bcca53e826660bff4e41c7d4bcb8dbea696404231a6f902f76ba41835d049e20f2dd6cffb713bf +"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": + version: 0.3.3 + resolution: "@jridgewell/gen-mapping@npm:0.3.3" + dependencies: + "@jridgewell/set-array": "npm:^1.0.1" + "@jridgewell/sourcemap-codec": "npm:^1.4.10" + "@jridgewell/trace-mapping": "npm:^0.3.9" + checksum: 376fc11cf5a967318ba3ddd9d8e91be528eab6af66810a713c49b0c3f8dc67e9949452c51c38ab1b19aa618fb5e8594da5a249977e26b1e7fea1ee5a1fcacc74 + languageName: node + linkType: hard + +"@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e + languageName: node + linkType: hard + +"@jridgewell/set-array@npm:^1.0.1": + version: 1.1.2 + resolution: "@jridgewell/set-array@npm:1.1.2" + checksum: bc7ab4c4c00470de4e7562ecac3c0c84f53e7ee8a711e546d67c47da7febe7c45cd67d4d84ee3c9b2c05ae8e872656cdded8a707a283d30bd54fbc65aef821ab languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10": +"@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: 0c6b5ae663087558039052a626d2d7ed5208da36cfd707dcc5cea4a07cfc918248403dcb5989a8f7afaf245ce0573b7cc6fd94c4a30453bd10e44d9363940ba5 @@ -1805,6 +3731,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.22 + resolution: "@jridgewell/trace-mapping@npm:0.3.22" + dependencies: + "@jridgewell/resolve-uri": "npm:^3.1.0" + "@jridgewell/sourcemap-codec": "npm:^1.4.14" + checksum: 18cf19f88e2792c1c91515f2b629aae05f3cdbb2e60c3886e16e80725234ce26dd10144c4981c05d9366e7094498c0b4fe5c1a89f4a730d7376a4ba4af448149 + languageName: node + linkType: hard + "@ljharb/resumer@npm:~0.0.1": version: 0.0.1 resolution: "@ljharb/resumer@npm:0.0.1" @@ -1815,11 +3751,37 @@ __metadata: linkType: hard "@ljharb/through@npm:^2.3.9, @ljharb/through@npm:~2.3.9": - version: 2.3.11 - resolution: "@ljharb/through@npm:2.3.11" + version: 2.3.12 + resolution: "@ljharb/through@npm:2.3.12" dependencies: - call-bind: "npm:^1.0.2" - checksum: 19cdaa9e4ba16aea9bb9dafbdd1c111febc0e5ce07b0959b049d7fda8a7247726603bb06b391f2d57227cf4ad081636d6f9e08dc138813225d54a6c81a04b679 + call-bind: "npm:^1.0.5" + checksum: 7560aaef7b6ef88c16783ffde37278e2177c7f0f5427400059a8a7687b144dc711bf5b2347ab27e858a29f25e4b868d77c915c9614bc399b82b8123430614653 + languageName: node + linkType: hard + +"@manypkg/find-root@npm:^1.1.0": + version: 1.1.0 + resolution: "@manypkg/find-root@npm:1.1.0" + dependencies: + "@babel/runtime": "npm:^7.5.5" + "@types/node": "npm:^12.7.1" + find-up: "npm:^4.1.0" + fs-extra: "npm:^8.1.0" + checksum: 0ee907698e6c73d6f1821ff630f3fec6dcf38260817c8752fec8991ac38b95ba431ab11c2773ddf9beb33d0e057f1122b00e8ffc9b8411b3fd24151413626fa6 + languageName: node + linkType: hard + +"@manypkg/get-packages@npm:^1.1.3": + version: 1.1.3 + resolution: "@manypkg/get-packages@npm:1.1.3" + dependencies: + "@babel/runtime": "npm:^7.5.5" + "@changesets/types": "npm:^4.0.1" + "@manypkg/find-root": "npm:^1.1.0" + fs-extra: "npm:^8.1.0" + globby: "npm:^11.0.0" + read-yaml-file: "npm:^1.1.0" + checksum: f05907d1174ae28861eaa06d0efdc144f773d9a4b8b65e1e7cdc01eb93361d335351b4a336e05c6aac02661be39e8809a3f7ad28bc67b6b338071434ab442130 languageName: node linkType: hard @@ -1843,12 +3805,12 @@ __metadata: languageName: node linkType: hard -"@noble/curves@npm:1.1.0, @noble/curves@npm:~1.1.0": - version: 1.1.0 - resolution: "@noble/curves@npm:1.1.0" +"@noble/curves@npm:1.3.0, @noble/curves@npm:~1.3.0": + version: 1.3.0 + resolution: "@noble/curves@npm:1.3.0" dependencies: - "@noble/hashes": "npm:1.3.1" - checksum: 81115c3ebfa7e7da2d7e18d44d686f98dc6d35dbde3964412c05707c92d0994a01545bc265d5c0bc05c8c49333f75b99c9acef6750f5a79b3abcc8e0546acf88 + "@noble/hashes": "npm:1.3.3" + checksum: 704bf8fda8e1365a9bb9e9945bd06645ef4ce85aa2fac5594abe09f19889197518152319481b89a271e0ee011787bd2ee87202441500bca7ca587a2c3ac10b01 languageName: node linkType: hard @@ -1859,17 +3821,10 @@ __metadata: languageName: node linkType: hard -"@noble/hashes@npm:1.3.1": - version: 1.3.1 - resolution: "@noble/hashes@npm:1.3.1" - checksum: 86512713aaf338bced594bc2046ab249fea4e1ba1e7f2ecd02151ef1b8536315e788c11608fafe1b56f04fad1aa3c602da7e5f8e5fcd5f8b0aa94435fe65278e - languageName: node - linkType: hard - -"@noble/hashes@npm:~1.3.0, @noble/hashes@npm:~1.3.1": - version: 1.3.2 - resolution: "@noble/hashes@npm:1.3.2" - checksum: 2482cce3bce6a596626f94ca296e21378e7a5d4c09597cbc46e65ffacc3d64c8df73111f2265444e36a3168208628258bbbaccba2ef24f65f58b2417638a20e7 +"@noble/hashes@npm:1.3.3, @noble/hashes@npm:~1.3.2": + version: 1.3.3 + resolution: "@noble/hashes@npm:1.3.3" + checksum: 23c020b33da4172c988e44100e33cd9f8f6250b68b43c467d3551f82070ebd9716e0d9d2347427aa3774c85934a35fa9ee6f026fca2117e3fa12db7bedae7668 languageName: node linkType: hard @@ -1936,18 +3891,17 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-block@npm:5.0.2": - version: 5.0.2 - resolution: "@nomicfoundation/ethereumjs-block@npm:5.0.2" +"@nomicfoundation/ethereumjs-block@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-block@npm:5.0.4" dependencies: - "@nomicfoundation/ethereumjs-common": "npm:4.0.2" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.2" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" + "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" ethereum-cryptography: "npm:0.1.3" - ethers: "npm:^5.7.1" - checksum: 9bbf524706c86b3741eab42a82bce723ef413f2ecd85bc96b6353f619559780995bc21fcf765558a3a7ab5eca5c77926ae7440fe2467774d896f67ec9bfcd63e + checksum: 9f8cb09f5910275188b1ad48611856c14131ad28022b958cc648f8e095fadd41002454a3396c612c2977691e59a8baad4f6adf07aab3f9c4b20b5f24c71dd7a0 languageName: node linkType: hard @@ -1992,24 +3946,21 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-blockchain@npm:7.0.2": - version: 7.0.2 - resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.2" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:5.0.2" - "@nomicfoundation/ethereumjs-common": "npm:4.0.2" - "@nomicfoundation/ethereumjs-ethash": "npm:3.0.2" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.2" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" - abstract-level: "npm:^1.0.3" +"@nomicfoundation/ethereumjs-blockchain@npm:7.0.4": + version: 7.0.4 + resolution: "@nomicfoundation/ethereumjs-blockchain@npm:7.0.4" + dependencies: + "@nomicfoundation/ethereumjs-block": "npm:5.0.4" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-ethash": "npm:3.0.4" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" + "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" debug: "npm:^4.3.3" ethereum-cryptography: "npm:0.1.3" - level: "npm:^8.0.0" - lru-cache: "npm:^5.1.1" - memory-level: "npm:^1.0.0" - checksum: 388f938288396669108e6513c531e81d02d994dabcbf96261dd6672a882dfd4966cf9e05fd0c98d50c7aef847335a588b21dd0acba9d923cc734f4f61a7a77ba + lru-cache: "npm:^10.0.0" + checksum: 47f73fea07880edb68b2614981226d9315a1a3dc673d0e09d68f0bc9ebd93cbfe6ccceb3cb56f777dc9b9386cff39878349fd7474d460a38478e7175b47788f9 languageName: node linkType: hard @@ -2033,13 +3984,12 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-common@npm:4.0.2": - version: 4.0.2 - resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.2" +"@nomicfoundation/ethereumjs-common@npm:4.0.4": + version: 4.0.4 + resolution: "@nomicfoundation/ethereumjs-common@npm:4.0.4" dependencies: - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" - crc-32: "npm:^1.2.0" - checksum: ce12038b8b3245a2a20b8a11fe19b4454a8179b7a1bb9185cd42a85b5a17f7fceacf0bf69517d095b52e3cede4eeda71a45044a5a8976f3f37e2d501f0adaea3 + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" + checksum: efaaebe41c2a3fe8b50bf12d9d134dc7611907f6eb2118f7822eaa375c54bc71bf6f6a3b2e22c754867f2cd28d619afd892b1eaa26cf1c886e0f793bda481070 languageName: node linkType: hard @@ -2071,17 +4021,16 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-ethash@npm:3.0.2": - version: 3.0.2 - resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.2" +"@nomicfoundation/ethereumjs-ethash@npm:3.0.4": + version: 3.0.4 + resolution: "@nomicfoundation/ethereumjs-ethash@npm:3.0.4" dependencies: - "@nomicfoundation/ethereumjs-block": "npm:5.0.2" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" - abstract-level: "npm:^1.0.3" - bigint-crypto-utils: "npm:^3.0.23" + "@nomicfoundation/ethereumjs-block": "npm:5.0.4" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" + bigint-crypto-utils: "npm:^3.2.2" ethereum-cryptography: "npm:0.1.3" - checksum: 0a19f9243e9cc348e13bff0b0ec5ec9612c275550c5b0a3028b466f39e0959dd8c0eeeae7fc0c9af920023143658dbb18d87107167af344de92e76aaf683dcc4 + checksum: c4cb846b656720910fe6d4a741ad0be93833c701456da983fa3a1795dda6faaa0ab4fb3130446e648db94b68358e1e4e30024d372fb40d3f65a40650af1a83bc languageName: node linkType: hard @@ -2117,19 +4066,19 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-evm@npm:2.0.2": - version: 2.0.2 - resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.2" +"@nomicfoundation/ethereumjs-evm@npm:2.0.4": + version: 2.0.4 + resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.4" dependencies: - "@ethersproject/providers": "npm:^5.7.1" - "@nomicfoundation/ethereumjs-common": "npm:4.0.2" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.4" + "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" + "@types/debug": "npm:^4.1.9" debug: "npm:^4.3.3" ethereum-cryptography: "npm:0.1.3" - mcl-wasm: "npm:^0.7.1" - rustbn.js: "npm:~0.2.0" - checksum: a5711952d8afe1c61c3e8275217b7c3bd600de839ad784848ff556c498fee4d0c0a29834aa2c666263915ed6123a3191297c109bad8e50c135dd9de33d101cd7 + rustbn-wasm: "npm:^0.2.0" + checksum: f21f4d0f1a74c903934d1c6c3abcd1342c9a812c71f142999c9f3f823119761cfdb4e89e829195fa446adb772b7f4b23ee9d55ed31bd92d5d03df438c3c29202 languageName: node linkType: hard @@ -2151,12 +4100,12 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-rlp@npm:5.0.2": - version: 5.0.2 - resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.2" +"@nomicfoundation/ethereumjs-rlp@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.4" bin: - rlp: bin/rlp - checksum: 46c7d317f59690973c41786b7a3ef3abe456efd085d55a0b202f6ead792e34e1a0749815911ab558b83f508c4ae5a6cba4d994aeae9c77c14ce0516f284ed34b + rlp: bin/rlp.cjs + checksum: 58e276c190f5f33e12ff4a2c7fe4c3c71cb139029eddd9b46488e23e168c422bc0b55368c0b7805ca8b09e9ea6b8298cd74c63f5c2ed4b6fb447635ed7a317f7 languageName: node linkType: hard @@ -2189,17 +4138,24 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-statemanager@npm:2.0.2": - version: 2.0.2 - resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.2" +"@nomicfoundation/ethereumjs-statemanager@npm:2.0.4": + version: 2.0.4 + resolution: "@nomicfoundation/ethereumjs-statemanager@npm:2.0.4" dependencies: - "@nomicfoundation/ethereumjs-common": "npm:4.0.2" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" debug: "npm:^4.3.3" ethereum-cryptography: "npm:0.1.3" - ethers: "npm:^5.7.1" js-sdsl: "npm:^4.1.4" - checksum: d3b184adb1b8aaf4c87299194746fc343a94df6f500d677f04a36914f7673eee19c344eb88a6f78718dcb4ae15d63c2c3e87cb9a5076950b67843e5bf9321ace + lru-cache: "npm:^10.0.0" + peerDependencies: + "@nomicfoundation/ethereumjs-verkle": 0.0.2 + peerDependenciesMeta: + "@nomicfoundation/ethereumjs-verkle": + optional: true + checksum: 6190fef25b1099ede00edf69194903a5c5df18563adae3f053e2eafacc91eeab547d257e6aa47ce7ff5264533bb7bb0fbfcb18e75ea66376ac7305ad40dafbf4 languageName: node linkType: hard @@ -2228,16 +4184,17 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-trie@npm:6.0.2": - version: 6.0.2 - resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.2" +"@nomicfoundation/ethereumjs-trie@npm:6.0.4": + version: 6.0.4 + resolution: "@nomicfoundation/ethereumjs-trie@npm:6.0.4" dependencies: - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" "@types/readable-stream": "npm:^2.3.13" ethereum-cryptography: "npm:0.1.3" + lru-cache: "npm:^10.0.0" readable-stream: "npm:^3.6.0" - checksum: 188c5d0a5793fb4512916091bde498e52ec6ecb374963213602f32e98c301d4d62f2daefd4ebefc0944d6d5b8346f104156fa544c0fc26ded488884a0424b2cc + checksum: b475d858f98037431c54c7177d0ce95133a81f1ee98a0b042136d65c88b7b5b3d86ba981cf78292776781d43d60daed44edf508ff4d416355bd00517e9142c9f languageName: node linkType: hard @@ -2267,17 +4224,20 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-tx@npm:5.0.2": - version: 5.0.2 - resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.2" +"@nomicfoundation/ethereumjs-tx@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.4" dependencies: - "@chainsafe/ssz": "npm:^0.9.2" - "@ethersproject/providers": "npm:^5.7.2" - "@nomicfoundation/ethereumjs-common": "npm:4.0.2" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" ethereum-cryptography: "npm:0.1.3" - checksum: 327c093656b4f6e845c3ef543b6ab54f6699436d95e18d0fca9df930dd2ddb975374b2499b3f98070cae4e6f54005b0484c1b40ff1838326cf5a631710116def + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 1e4ba6d7d6aa8d44a807e3332e98e8fbea70c1aa91be3b39b581c4b498554ee380eec21442d737d2b646c722da306dd1179a5e37747b285b93690aab041d52a7 languageName: node linkType: hard @@ -2302,14 +4262,30 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-util@npm:9.0.2": - version: 9.0.2 - resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.2" +"@nomicfoundation/ethereumjs-util@npm:9.0.4": + version: 9.0.4 + resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" dependencies: - "@chainsafe/ssz": "npm:^0.10.0" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" ethereum-cryptography: "npm:0.1.3" - checksum: 34b5b73f2e23bd883e53fd4d6810954d08451c84887b3d7c8910c093825686c499fe0edbb865db8d064c6790b447ce10f1aea030073befd64dbe62b75126dac6 + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 228e8cb018ce6b487a0eb65c585d692b56bb306a26df3f6f063cdf87feea6174b005b25f2dc4547b940f76d0d6c4bcaa8ffbbcce482091168cdf3c6fe2f8b5da + languageName: node + linkType: hard + +"@nomicfoundation/ethereumjs-verkle@npm:0.0.2": + version: 0.0.2 + resolution: "@nomicfoundation/ethereumjs-verkle@npm:0.0.2" + dependencies: + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" + lru-cache: "npm:^10.0.0" + rust-verkle-wasm: "npm:^0.0.1" + checksum: 7f6b3be75949adbdb8ecea4539a7c4cdce9ee1d76159b5d77f04a794e4e9de42570fc0491fc4769ecc3553547031996b16ec88ba18d68bf0e1b0d1149effb51b languageName: node linkType: hard @@ -2334,24 +4310,22 @@ __metadata: languageName: node linkType: hard -"@nomicfoundation/ethereumjs-vm@npm:7.0.2": - version: 7.0.2 - resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.2" - dependencies: - "@nomicfoundation/ethereumjs-block": "npm:5.0.2" - "@nomicfoundation/ethereumjs-blockchain": "npm:7.0.2" - "@nomicfoundation/ethereumjs-common": "npm:4.0.2" - "@nomicfoundation/ethereumjs-evm": "npm:2.0.2" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" - "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.2" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.2" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" +"@nomicfoundation/ethereumjs-vm@npm:7.0.4": + version: 7.0.4 + resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.4" + dependencies: + "@nomicfoundation/ethereumjs-block": "npm:5.0.4" + "@nomicfoundation/ethereumjs-blockchain": "npm:7.0.4" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-evm": "npm:2.0.4" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.4" + "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" + "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" debug: "npm:^4.3.3" ethereum-cryptography: "npm:0.1.3" - mcl-wasm: "npm:^0.7.1" - rustbn.js: "npm:~0.2.0" - checksum: 759c16d471429e06b8a191b3b87c140690e6334586b5467587e7397e7e40dc0ec6aea4a73cea68a1ace125552beefc23624a6e667387031f5379000e56f83018 + checksum: a1893c8aa0fb8666bcb7371d8a57f641bd6079a79f9e08175aca214cd4a3d7eda3e54046a7d1b4c6cbc2356e80b1e6b44295e56df2d184ceb157eb67e54ee326 languageName: node linkType: hard @@ -2380,13 +4354,13 @@ __metadata: linkType: hard "@nomicfoundation/hardhat-network-helpers@npm:^1.0.9": - version: 1.0.9 - resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.0.9" + version: 1.0.10 + resolution: "@nomicfoundation/hardhat-network-helpers@npm:1.0.10" dependencies: ethereumjs-util: "npm:^7.1.4" peerDependencies: hardhat: ^2.9.5 - checksum: ff3588875d7c486618fa485f0929fe23b1ea951a34ac385b778ebf9a78532db7fb88ab3cb01d71d14441b2e2ea2c7835b6e81aacb04c12cbfe9294add09c83c9 + checksum: ff41875b2ece46ae33d144d83e8f43fbef18c7387d069a939cdbce1581cae83f415ca3477799e26dabe5e8faea7aadee4c4b4a90460f06b5b5e5aa02f9a2e4dd languageName: node linkType: hard @@ -2499,7 +4473,7 @@ __metadata: languageName: node linkType: hard -"@nomiclabs/hardhat-ethers@npm:^2.2.3": +"@nomiclabs/hardhat-ethers@npm:^2.0.0, @nomiclabs/hardhat-ethers@npm:^2.2.3": version: 2.2.3 resolution: "@nomiclabs/hardhat-ethers@npm:2.2.3" peerDependencies: @@ -2510,8 +4484,8 @@ __metadata: linkType: hard "@nomiclabs/hardhat-etherscan@npm:^3.1.7": - version: 3.1.7 - resolution: "@nomiclabs/hardhat-etherscan@npm:3.1.7" + version: 3.1.8 + resolution: "@nomiclabs/hardhat-etherscan@npm:3.1.8" dependencies: "@ethersproject/abi": "npm:^5.1.2" "@ethersproject/address": "npm:^5.0.2" @@ -2525,7 +4499,7 @@ __metadata: undici: "npm:^5.14.0" peerDependencies: hardhat: ^2.0.4 - checksum: 3302820ac823fcb07a5ba278f3e2f07a7f6ba5e0679f0694860a2a189e91188993cc51a0001ec38c532381d3367da72dfcc9820c08ed6e5e0337651bf351dd9e + checksum: 7869e14506794f4ca2da147b99e0775a1e7d1afc3fd35fae53d65a1a01df67748a583e99fd4ef557af2cba4ed59ed1400510ef72b0728d64de67dbbc5742746f languageName: node linkType: hard @@ -2544,16 +4518,29 @@ __metadata: languageName: node linkType: hard +"@nomiclabs/hardhat-waffle@npm:^2.0.0": + version: 2.0.6 + resolution: "@nomiclabs/hardhat-waffle@npm:2.0.6" + peerDependencies: + "@nomiclabs/hardhat-ethers": ^2.0.0 + "@types/sinon-chai": ^3.2.3 + ethereum-waffle: "*" + ethers: ^5.0.0 + hardhat: ^2.0.0 + checksum: 9614ab1e76959cfccc586842d990de4c2aa74cea8e82a838d017d91d4c696df931af4a77af9c16325e037ec8438a8c98c9bae5d9e4d0d0fcdaa147c86bce01b5 + languageName: node + linkType: hard + "@npmcli/agent@npm:^2.0.0": - version: 2.2.0 - resolution: "@npmcli/agent@npm:2.2.0" + version: 2.2.1 + resolution: "@npmcli/agent@npm:2.2.1" dependencies: agent-base: "npm:^7.1.0" http-proxy-agent: "npm:^7.0.0" https-proxy-agent: "npm:^7.0.1" lru-cache: "npm:^10.0.1" socks-proxy-agent: "npm:^8.0.1" - checksum: 7b89590598476dda88e79c473766b67c682aae6e0ab0213491daa6083dcc0c171f86b3868f5506f22c09aa5ea69ad7dfb78f4bf39a8dca375d89a42f408645b3 + checksum: 38ee5cbe8f3cde13be916e717bfc54fd1a7605c07af056369ff894e244c221e0b56b08ca5213457477f9bc15bca9e729d51a4788829b5c3cf296b3c996147f76 languageName: node linkType: hard @@ -2573,7 +4560,7 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/contracts@npm:^3.4.1": +"@openzeppelin/contracts@npm:^3.3.0-solc-0.7, @openzeppelin/contracts@npm:^3.4.1": version: 3.4.2 resolution: "@openzeppelin/contracts@npm:3.4.2" checksum: 92e7047d889d9beb6675951d07f4bde8c0ca4f20d93d50c7f7b6bb1cd7dd072c88bf71c4f0be8ad9a28ad1031b8e471463fb338936914514e74cd32bf287ad1f @@ -2581,28 +4568,28 @@ __metadata: linkType: hard "@openzeppelin/defender-admin-client@npm:^1.46.0": - version: 1.52.0 - resolution: "@openzeppelin/defender-admin-client@npm:1.52.0" + version: 1.54.1 + resolution: "@openzeppelin/defender-admin-client@npm:1.54.1" dependencies: - "@openzeppelin/defender-base-client": "npm:1.52.0" + "@openzeppelin/defender-base-client": "npm:1.54.1" axios: "npm:^1.4.0" ethers: "npm:^5.7.2" lodash: "npm:^4.17.19" node-fetch: "npm:^2.6.0" - checksum: 97b0612c6ef2505506d14518947eca6766ce442ac4ad685e3b3fcdb9d8f28da5b4f10575a6312e1b3571eff6345b359c764ead4cc82949da2a7b39e376268f71 + checksum: b8d9b112bc9c477aca23a9b7249801eb997295302afe60e5c0883579f1ca1069a411ee7be9f972de52019bf59e0d36b7c11503ec09d4328c15899fa4bfdf6d6c languageName: node linkType: hard -"@openzeppelin/defender-base-client@npm:1.52.0, @openzeppelin/defender-base-client@npm:^1.46.0": - version: 1.52.0 - resolution: "@openzeppelin/defender-base-client@npm:1.52.0" +"@openzeppelin/defender-base-client@npm:1.54.1, @openzeppelin/defender-base-client@npm:^1.46.0": + version: 1.54.1 + resolution: "@openzeppelin/defender-base-client@npm:1.54.1" dependencies: amazon-cognito-identity-js: "npm:^6.0.1" async-retry: "npm:^1.3.3" axios: "npm:^1.4.0" lodash: "npm:^4.17.19" node-fetch: "npm:^2.6.0" - checksum: 0927be204dfa5d825bfca755f2e251ed4b068c0f78585db975d2ef7ea524d4c61082d75ec03ce12bdb68d62343cc2ec5a1ffbaebe2c4a1664b1c9623692bad76 + checksum: 10a709dfc4fc55ad8d431b1c6d5e67129131d9763f3a91b9ec9ee63653cc8b0a8567809d04341bcb8615e0e20c917c2045a45693070ee9d83da11620338d874d languageName: node linkType: hard @@ -2618,7 +4605,7 @@ __metadata: languageName: node linkType: hard -"@openzeppelin/hardhat-upgrades@npm:^1.20.0, @openzeppelin/hardhat-upgrades@npm:^1.6.0": +"@openzeppelin/hardhat-upgrades@npm:^1.20.0, @openzeppelin/hardhat-upgrades@npm:^1.22.1, @openzeppelin/hardhat-upgrades@npm:^1.6.0": version: 1.28.0 resolution: "@openzeppelin/hardhat-upgrades@npm:1.28.0" dependencies: @@ -2656,8 +4643,8 @@ __metadata: linkType: hard "@openzeppelin/upgrades-core@npm:^1.27.0": - version: 1.31.3 - resolution: "@openzeppelin/upgrades-core@npm:1.31.3" + version: 1.32.5 + resolution: "@openzeppelin/upgrades-core@npm:1.32.5" dependencies: cbor: "npm:^9.0.0" chalk: "npm:^4.1.0" @@ -2669,7 +4656,40 @@ __metadata: solidity-ast: "npm:^0.4.51" bin: openzeppelin-upgrades-core: dist/cli/cli.js - checksum: 7b40bd2cbdb53e76bb3b319b8f70bdcbd6cc473290aa8950dff243603be987456e2ef90f7ca75f7f5b70c5ca652f052d5b9d518d30f5b025fb9b09e5d8624777 + checksum: aac654c46aadcfba55024a17d029edcbc529be2fae16fa8d4efc3fd8114cbb4d36d8974a62b1f34fcfa593b3b072898995034ff3bb6a921e00bcac669d8b1998 + languageName: node + linkType: hard + +"@peculiar/asn1-schema@npm:^2.3.8": + version: 2.3.8 + resolution: "@peculiar/asn1-schema@npm:2.3.8" + dependencies: + asn1js: "npm:^3.0.5" + pvtsutils: "npm:^1.3.5" + tslib: "npm:^2.6.2" + checksum: 65f16b2a7eb91365b6dac47730ffcad4617ef04b821e0a4286c379ac7283588b0a6744032ee686e0914a0886c2a055108ed945b9c4d22821a3b123640b61f3b2 + languageName: node + linkType: hard + +"@peculiar/json-schema@npm:^1.1.12": + version: 1.1.12 + resolution: "@peculiar/json-schema@npm:1.1.12" + dependencies: + tslib: "npm:^2.0.0" + checksum: 202132c66dcc6b6aca5d0af971c015be2e163da2f7f992910783c5d39c8a7db59b6ec4f4ce419459a1f954b7e1d17b6b253f0e60072c1b3d254079f4eaebc311 + languageName: node + linkType: hard + +"@peculiar/webcrypto@npm:^1.4.0": + version: 1.4.5 + resolution: "@peculiar/webcrypto@npm:1.4.5" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/json-schema": "npm:^1.1.12" + pvtsutils: "npm:^1.3.5" + tslib: "npm:^2.6.2" + webcrypto-core: "npm:^1.7.8" + checksum: 7cefe2a1329e3d41721268cf483dfd7a7a3bfbdaaba0ca8db9a538b49a51c6977f66f7f85e6f0c2162ff8d09540821bedc6766586d83c4be565b1af49ea81a86 languageName: node linkType: hard @@ -2680,17 +4700,60 @@ __metadata: languageName: node linkType: hard -"@pkgr/utils@npm:^2.3.1": - version: 2.4.2 - resolution: "@pkgr/utils@npm:2.4.2" +"@pkgr/core@npm:^0.1.0": + version: 0.1.1 + resolution: "@pkgr/core@npm:0.1.1" + checksum: 3f7536bc7f57320ab2cf96f8973664bef624710c403357429fbf680a5c3b4843c1dbd389bb43daa6b1f6f1f007bb082f5abcb76bb2b5dc9f421647743b71d3d8 + languageName: node + linkType: hard + +"@pnpm/config.env-replace@npm:^1.1.0": + version: 1.1.0 + resolution: "@pnpm/config.env-replace@npm:1.1.0" + checksum: 4cfc4a5c49ab3d0c6a1f196cfd4146374768b0243d441c7de8fa7bd28eaab6290f514b98490472cc65dbd080d34369447b3e9302585e1d5c099befd7c8b5e55f + languageName: node + linkType: hard + +"@pnpm/network.ca-file@npm:^1.0.1": + version: 1.0.2 + resolution: "@pnpm/network.ca-file@npm:1.0.2" dependencies: - cross-spawn: "npm:^7.0.3" - fast-glob: "npm:^3.3.0" - is-glob: "npm:^4.0.3" - open: "npm:^9.1.0" - picocolors: "npm:^1.0.0" - tslib: "npm:^2.6.0" - checksum: 7c3e68f6405a1d4c51f418d8d580e71d7bade2683d5db07e8413d8e57f7e389047eda44a2341f77a1b3085895fca7676a9d45e8812a58312524f8c4c65d501be + graceful-fs: "npm:4.2.10" + checksum: 95f6e0e38d047aca3283550719155ce7304ac00d98911e4ab026daedaf640a63bd83e3d13e17c623fa41ac72f3801382ba21260bcce431c14fbbc06430ecb776 + languageName: node + linkType: hard + +"@pnpm/npm-conf@npm:^2.1.0": + version: 2.2.2 + resolution: "@pnpm/npm-conf@npm:2.2.2" + dependencies: + "@pnpm/config.env-replace": "npm:^1.1.0" + "@pnpm/network.ca-file": "npm:^1.0.1" + config-chain: "npm:^1.1.11" + checksum: 71393dcfce85603fddd8484b486767163000afab03918303253ae97992615b91d25942f83751366cb40ad2ee32b0ae0a033561de9d878199a024286ff98b0296 + languageName: node + linkType: hard + +"@prettier/sync@npm:^0.3.0": + version: 0.3.0 + resolution: "@prettier/sync@npm:0.3.0" + peerDependencies: + prettier: ^3.0.0 + checksum: 54f2522da9ee2192d89c7fb15e6c362adc8a4d834be1c3c38a14b5fd5a02239a74ef3adc50df9b6794d9e76b0bb66be2bcc8d30017f85232b7cdb98d5e140b1c + languageName: node + linkType: hard + +"@repeaterjs/repeater@npm:3.0.4": + version: 3.0.4 + resolution: "@repeaterjs/repeater@npm:3.0.4" + checksum: 9a2928d70f2be4a8f72857f8f7553810015ac970f174b4b20f07289644379af57fa68947601d67e557c1a7c33ddf805e787cf2a1d5e9037ba485d24075a81b6b + languageName: node + linkType: hard + +"@repeaterjs/repeater@npm:^3.0.4": + version: 3.0.5 + resolution: "@repeaterjs/repeater@npm:3.0.5" + checksum: e6e1aca2bbfe0b8e974bc5185a6839f9e78ec8acb96b6d6911a9dfc958443689f9bc38bcc6d554e6c8598f597f0151841aafbd1ee3ef16262ee93d18b2c1d4b5 languageName: node linkType: hard @@ -2739,10 +4802,10 @@ __metadata: languageName: node linkType: hard -"@scure/base@npm:~1.1.0": - version: 1.1.3 - resolution: "@scure/base@npm:1.1.3" - checksum: 4eb1d8b58da503ecdff743be36ae3562bbff724da82fb3401468d348659841ae4bb271aeae3a8cf6c4d06cd887dee3825ce6fdac2f699afc63838ae68c499baa +"@scure/base@npm:^1.1.1, @scure/base@npm:~1.1.0, @scure/base@npm:~1.1.4": + version: 1.1.5 + resolution: "@scure/base@npm:1.1.5" + checksum: 6eb07be0202fac74a57c79d0d00a45f6f7e57447010c1e3d90a4275d197829727b7abc54b248fc6f9bef9ae374f7be5ee9154dde5b5b73da773560bf17aa8504 languageName: node linkType: hard @@ -2757,14 +4820,14 @@ __metadata: languageName: node linkType: hard -"@scure/bip32@npm:1.3.1": - version: 1.3.1 - resolution: "@scure/bip32@npm:1.3.1" +"@scure/bip32@npm:1.3.3": + version: 1.3.3 + resolution: "@scure/bip32@npm:1.3.3" dependencies: - "@noble/curves": "npm:~1.1.0" - "@noble/hashes": "npm:~1.3.1" - "@scure/base": "npm:~1.1.0" - checksum: 9ff0ad56f512794aed1ed62e582bf855db829e688235420a116b210169dc31e3e2a8cc4a908126aaa07b6dcbcc4cd085eb12f9d0a8b507a88946d6171a437195 + "@noble/curves": "npm:~1.3.0" + "@noble/hashes": "npm:~1.3.2" + "@scure/base": "npm:~1.1.4" + checksum: 48fa04ebf0e3b56e3d086f029ae207ea753d8d8a1b3564f3c80fafea63dc3ee4edbd21e44eadb79bd4de4afffb075cbbbcb258fd5030a9680065cb524424eb83 languageName: node linkType: hard @@ -2778,13 +4841,13 @@ __metadata: languageName: node linkType: hard -"@scure/bip39@npm:1.2.1": - version: 1.2.1 - resolution: "@scure/bip39@npm:1.2.1" +"@scure/bip39@npm:1.2.2": + version: 1.2.2 + resolution: "@scure/bip39@npm:1.2.2" dependencies: - "@noble/hashes": "npm:~1.3.0" - "@scure/base": "npm:~1.1.0" - checksum: fe951f69dd5a7cdcefbe865bce1b160d6b59ba19bd01d09f0718e54fce37a7d8be158b32f5455f0e9c426a7fbbede3e019bf0baa99bacc88ef26a76a07e115d4 + "@noble/hashes": "npm:~1.3.2" + "@scure/base": "npm:~1.1.4" + checksum: be38bc1dc10b9a763d8b02d91dc651a4f565c822486df6cb1d3cc84896c1aab3ef6acbf7b3dc7e4a981bc9366086a4d72020aa21e11a692734a750de049c887c languageName: node linkType: hard @@ -2884,12 +4947,19 @@ __metadata: languageName: node linkType: hard -"@smithy/types@npm:^2.5.0": - version: 2.6.0 - resolution: "@smithy/types@npm:2.6.0" +"@sindresorhus/is@npm:^5.2.0": + version: 5.6.0 + resolution: "@sindresorhus/is@npm:5.6.0" + checksum: 66727344d0c92edde5760b5fd1f8092b717f2298a162a5f7f29e4953e001479927402d9d387e245fb9dc7d3b37c72e335e93ed5875edfc5203c53be8ecba1b52 + languageName: node + linkType: hard + +"@smithy/types@npm:^2.9.1": + version: 2.10.0 + resolution: "@smithy/types@npm:2.10.0" dependencies: tslib: "npm:^2.5.0" - checksum: 10c47947d8c3054ef4525da852330f1ef7030578a887bc3edd5853f65f229cf22c68512da4c952e1431dc992c4d62a21432440475c3e66ab2c7032ed03591251 + checksum: e82d7584e9b0d0c8fb6da059af6ebcb8af86dba7c1dc3e757b4998eca636f8dd697ea47701ff6c755789f0a63ef16f960fcc682ab2ca185cef4c6a6db5f022dc languageName: node linkType: hard @@ -2911,6 +4981,82 @@ __metadata: languageName: node linkType: hard +"@solidity-parser/parser@npm:^0.17.0": + version: 0.17.0 + resolution: "@solidity-parser/parser@npm:0.17.0" + checksum: de606abd2f603b8056828c772de3f26b0d92913d0e8ebe4f2c149485f548e1b7af308c54c569542b3fc8e03d3219a9fb0a318f56b92b3042074c8074c1da53f2 + languageName: node + linkType: hard + +"@stylistic/eslint-plugin-js@npm:1.6.2, @stylistic/eslint-plugin-js@npm:^1.6.2": + version: 1.6.2 + resolution: "@stylistic/eslint-plugin-js@npm:1.6.2" + dependencies: + "@types/eslint": "npm:^8.56.2" + acorn: "npm:^8.11.3" + escape-string-regexp: "npm:^4.0.0" + eslint-visitor-keys: "npm:^3.4.3" + espree: "npm:^9.6.1" + peerDependencies: + eslint: ">=8.40.0" + checksum: b74b08802cb888b64b2432e2fa7723c664d1b6a3ee5ad48f8caeef83eebcfcf291f92f967b65e79854d19a660e9428567247de402eeb9e59d9320f71c8c3881e + languageName: node + linkType: hard + +"@stylistic/eslint-plugin-jsx@npm:1.6.2": + version: 1.6.2 + resolution: "@stylistic/eslint-plugin-jsx@npm:1.6.2" + dependencies: + "@stylistic/eslint-plugin-js": "npm:^1.6.2" + "@types/eslint": "npm:^8.56.2" + estraverse: "npm:^5.3.0" + picomatch: "npm:^4.0.1" + peerDependencies: + eslint: ">=8.40.0" + checksum: 882daa8ac9e3d7db5009dd6a9b4c406edab0ced233d3d49e6a9a0acb94ed68d8e5ec9a705c8925c7adc103ef9c057f33b74c32c7087f40a61c5b85f31f530fcc + languageName: node + linkType: hard + +"@stylistic/eslint-plugin-plus@npm:1.6.2": + version: 1.6.2 + resolution: "@stylistic/eslint-plugin-plus@npm:1.6.2" + dependencies: + "@types/eslint": "npm:^8.56.2" + "@typescript-eslint/utils": "npm:^6.21.0" + peerDependencies: + eslint: "*" + checksum: 426e68c7edcb96d48f8ccb22c07fb5b7b26d85210494cfbafb6331d67496946ae3af841933059c31594d5f7c8b4e867de2345418d64a1885b102988d7679fae1 + languageName: node + linkType: hard + +"@stylistic/eslint-plugin-ts@npm:1.6.2": + version: 1.6.2 + resolution: "@stylistic/eslint-plugin-ts@npm:1.6.2" + dependencies: + "@stylistic/eslint-plugin-js": "npm:1.6.2" + "@types/eslint": "npm:^8.56.2" + "@typescript-eslint/utils": "npm:^6.21.0" + peerDependencies: + eslint: ">=8.40.0" + checksum: 15e19abfce7ac77843d1331ee5cab74b405bdb5fb890acb071f6a7c21dc81b338d6482f227aa0af0b32faa61de25166b3a3253cec1df867f99ca105155e001cc + languageName: node + linkType: hard + +"@stylistic/eslint-plugin@npm:^1.6.2": + version: 1.6.2 + resolution: "@stylistic/eslint-plugin@npm:1.6.2" + dependencies: + "@stylistic/eslint-plugin-js": "npm:1.6.2" + "@stylistic/eslint-plugin-jsx": "npm:1.6.2" + "@stylistic/eslint-plugin-plus": "npm:1.6.2" + "@stylistic/eslint-plugin-ts": "npm:1.6.2" + "@types/eslint": "npm:^8.56.2" + peerDependencies: + eslint: ">=8.40.0" + checksum: 353c852e1ace9b80bfe18a31b977723d79081397a12ebd14f34f2f5c2eeebc71a38ea17b65b9e3e3d8fcf09c14807822bf9123551e8df1785a3d1d1a6ee39c51 + languageName: node + linkType: hard + "@szmarczak/http-timer@npm:^1.1.2": version: 1.1.2 resolution: "@szmarczak/http-timer@npm:1.1.2" @@ -3110,9 +5256,9 @@ __metadata: linkType: hard "@types/chai@npm:*, @types/chai@npm:^4.3.9": - version: 4.3.11 - resolution: "@types/chai@npm:4.3.11" - checksum: 0c216ac4a19bfbf8318bb104d32e50704ee2ffc4b538b976c4326e6638fee121462402caa570662227a2a218810388aadb14bdbd3d3d474ec300b00695db448a + version: 4.3.12 + resolution: "@types/chai@npm:4.3.12" + checksum: e5d952726d7f053812579962b07d0e4965c160c6a90bf466580e639cd3a1f1d30da1abbfe782383538a043a07908f9dfb823fa9065b37752a5f27d62234f44d5 languageName: node linkType: hard @@ -3125,7 +5271,7 @@ __metadata: languageName: node linkType: hard -"@types/debug@npm:^4.1.10, @types/debug@npm:^4.1.7, @types/debug@npm:^4.1.8": +"@types/debug@npm:^4.1.10, @types/debug@npm:^4.1.7, @types/debug@npm:^4.1.8, @types/debug@npm:^4.1.9": version: 4.1.12 resolution: "@types/debug@npm:4.1.12" dependencies: @@ -3134,12 +5280,38 @@ __metadata: languageName: node linkType: hard -"@types/dotenv@npm:^8.2.0": - version: 8.2.0 - resolution: "@types/dotenv@npm:8.2.0" - dependencies: - dotenv: "npm:*" - checksum: cd010440ea750acf2359fb9ed0a1681b00ce29d9c40b602fe33e51642bd44ce30ced54b23fadc05385daa415fe9f671273911bcf95381a5aaf09690b3db96938 +"@types/dotenv@npm:^8.2.0": + version: 8.2.0 + resolution: "@types/dotenv@npm:8.2.0" + dependencies: + dotenv: "npm:*" + checksum: cd010440ea750acf2359fb9ed0a1681b00ce29d9c40b602fe33e51642bd44ce30ced54b23fadc05385daa415fe9f671273911bcf95381a5aaf09690b3db96938 + languageName: node + linkType: hard + +"@types/eslint@npm:*, @types/eslint@npm:^8.56.2": + version: 8.56.3 + resolution: "@types/eslint@npm:8.56.3" + dependencies: + "@types/estree": "npm:*" + "@types/json-schema": "npm:*" + checksum: c5d81d0001fae211451b39d82b2bc8d7224b00d52a514954a33840a3665f36f3bde3be602eec6ad08d1fff59108052cd7746ced4237116bc3d8ac01a7cf5b5fe + languageName: node + linkType: hard + +"@types/eslint__js@npm:^8.42.3": + version: 8.42.3 + resolution: "@types/eslint__js@npm:8.42.3" + dependencies: + "@types/eslint": "npm:*" + checksum: ccc5180b92155929a089ffb03ed62625216dcd5e46dd3197c6f82370ce8b52c7cb9df66c06b0a3017995409e023bc9eafe5a3f009e391960eacefaa1b62d9a56 + languageName: node + linkType: hard + +"@types/estree@npm:*": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d languageName: node linkType: hard @@ -3169,7 +5341,7 @@ __metadata: languageName: node linkType: hard -"@types/http-cache-semantics@npm:*": +"@types/http-cache-semantics@npm:*, @types/http-cache-semantics@npm:^4.0.2": version: 4.0.4 resolution: "@types/http-cache-semantics@npm:4.0.4" checksum: 51b72568b4b2863e0fe8d6ce8aad72a784b7510d72dc866215642da51d84945a9459fa89f49ec48f1e9a1752e6a78e85a4cda0ded06b1c73e727610c925f9ce6 @@ -3196,7 +5368,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.7": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db @@ -3263,6 +5435,13 @@ __metadata: languageName: node linkType: hard +"@types/mocha@npm:^9.1.0": + version: 9.1.1 + resolution: "@types/mocha@npm:9.1.1" + checksum: d033742ce0c92b917815b6e515165ee396866d0db0c0bbe0c301e49402abe3a61bd51e5bb1df7577f1fac60c99ee505fa744f515b476cc934ecb57f709f327e9 + languageName: node + linkType: hard + "@types/ms@npm:*": version: 0.7.34 resolution: "@types/ms@npm:0.7.34" @@ -3271,21 +5450,21 @@ __metadata: linkType: hard "@types/node-fetch@npm:^2.5.5": - version: 2.6.9 - resolution: "@types/node-fetch@npm:2.6.9" + version: 2.6.11 + resolution: "@types/node-fetch@npm:2.6.11" dependencies: "@types/node": "npm:*" form-data: "npm:^4.0.0" - checksum: b15b6d518ea4dd4a21cf328e9df0a88b2e5b76f3455ddfeb9063a3b97087c50b15ab195a869dadbbeb09d08dcc915557fb6a4f72b4fe79ee42e215fce3d9b0db + checksum: 5283d4e0bcc37a5b6d8e629aee880a4ffcfb33e089f4b903b2981b19c623972d1e64af7c3f9540ab990f0f5c89b9b5dda19c5bcb37a8e177079e93683bfd2f49 languageName: node linkType: hard -"@types/node@npm:*, @types/node@npm:^20.9.0": - version: 20.10.0 - resolution: "@types/node@npm:20.10.0" +"@types/node@npm:*, @types/node@npm:^20.11.19, @types/node@npm:^20.4.2, @types/node@npm:^20.8.7, @types/node@npm:^20.9.0": + version: 20.11.20 + resolution: "@types/node@npm:20.11.20" dependencies: undici-types: "npm:~5.26.4" - checksum: f379e57d9d28cb5f3d8eab943de0c54a0ca2f95ee356e1fe2a1a4fa718b740103ae522c50ce107cffd52c3642ef3244cfc55bf5369081dd6c48369c8587b21ae + checksum: 8e8de211e6d54425c603388a9b5cc9c434101985d0a1c88aabbf65d10df2b1fccd71855c20e61ae8a75c7aea56cb0f64e722cf7914cff1247d0b62ce21996ac4 languageName: node linkType: hard @@ -3296,31 +5475,13 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^12.12.6": +"@types/node@npm:^12.12.6, @types/node@npm:^12.7.1": version: 12.20.55 resolution: "@types/node@npm:12.20.55" checksum: 3b190bb0410047d489c49bbaab592d2e6630de6a50f00ba3d7d513d59401d279972a8f5a598b5bb8ddc1702f8a2f4ec57a65d93852f9c329639738e7053637d1 languageName: node linkType: hard -"@types/node@npm:^18.11.9": - version: 18.18.13 - resolution: "@types/node@npm:18.18.13" - dependencies: - undici-types: "npm:~5.26.4" - checksum: 5f1840f26b4c00e6b4945be678644a46e6689ef10d9d7795d587b76059045b99a14ca6075264296e6e91d73e098fe83df9580881278d9a6ce394b368d9c76700 - languageName: node - linkType: hard - -"@types/node@npm:^20.8.7": - version: 20.10.1 - resolution: "@types/node@npm:20.10.1" - dependencies: - undici-types: "npm:~5.26.4" - checksum: c1b4b5a33f57bd39a8a0d074f27e3e370fccc6cda6a1c46caa48cc4c1687677cfdbffd9dc93fc803c6d355696dd9c73cd6f6507c749f61f83beb7326aec077d2 - languageName: node - linkType: hard - "@types/node@npm:^8.0.0": version: 8.10.66 resolution: "@types/node@npm:8.10.66" @@ -3358,10 +5519,10 @@ __metadata: languageName: node linkType: hard -"@types/qs@npm:^6.2.31": - version: 6.9.10 - resolution: "@types/qs@npm:6.9.10" - checksum: 6be12e5f062d1b41eb037d59bf9cb65bc9410cedd5e6da832dfd7c8e2b3f4c91e81c9b90b51811140770e5052c6c4e8361181bd9437ddcd4515dc128b7c00353 +"@types/qs@npm:^6.2.31, @types/qs@npm:^6.9.4": + version: 6.9.11 + resolution: "@types/qs@npm:6.9.11" + checksum: 657a50f05b694d6fd3916d24177cfa0f3b8b87d9deff4ffa4dddcb0b03583ebf7c47b424b8de400270fb9a5cc1e9cf790dd82c833c6935305851e7da8ede3ff5 languageName: node linkType: hard @@ -3403,9 +5564,9 @@ __metadata: linkType: hard "@types/semver@npm:^7.5.0": - version: 7.5.6 - resolution: "@types/semver@npm:7.5.6" - checksum: 196dc32db5f68cbcde2e6a42bb4aa5cbb100fa2b7bd9c8c82faaaf3e03fbe063e205dbb4f03c7cdf53da2edb70a0d34c9f2e601b54281b377eb8dc1743226acd + version: 7.5.7 + resolution: "@types/semver@npm:7.5.7" + checksum: fb72d8b86a7779650f14ae89542f1da2ab624adb8188d98754b1d29a2fe3d41f0348bf9435b60ad145df1812fd2a09b3256779aa23b532c199f3dee59619a1eb languageName: node linkType: hard @@ -3420,11 +5581,11 @@ __metadata: linkType: hard "@types/sinon@npm:*": - version: 17.0.2 - resolution: "@types/sinon@npm:17.0.2" + version: 17.0.3 + resolution: "@types/sinon@npm:17.0.3" dependencies: "@types/sinonjs__fake-timers": "npm:*" - checksum: 0794a7c2ebdef397f510db0ccbfa242d4ae52db88f0f0e23e087f569e8ff76b6466680d96209b511acc0f3c08bb70dac6e51c0c2a4f62dfd1faf34f6cb308498 + checksum: 6fc3aa497fd87826375de3dbddc2bf01c281b517c32c05edf95b5ad906382dc221bca01ca9d44fc7d5cb4c768f996f268154e87633a45b3c0b5cddca7ef5e2be languageName: node linkType: hard @@ -3459,9 +5620,9 @@ __metadata: linkType: hard "@types/validator@npm:^13.7.1, @types/validator@npm:^13.7.17": - version: 13.11.7 - resolution: "@types/validator@npm:13.11.7" - checksum: 9ca2a047d6e7c1d718c6dd28b12d6d893c4ac2acdb8a557b8d448dab17aaa044e92c7a13c8476601078f4c907ed66259e3b20525f7fa849378fbaf53a971d574 + version: 13.11.9 + resolution: "@types/validator@npm:13.11.9" + checksum: 856ebfcfe25d6c91a90235e0eb27302a737832530898195bbfb265da52ae7fe6d68f684942574f8818d3c262cae7a1de99f145dac73fc57217933af1bfc199cb languageName: node linkType: hard @@ -3484,6 +5645,15 @@ __metadata: languageName: node linkType: hard +"@types/ws@npm:^8.0.0": + version: 8.5.10 + resolution: "@types/ws@npm:8.5.10" + dependencies: + "@types/node": "npm:*" + checksum: e9af279b984c4a04ab53295a40aa95c3e9685f04888df5c6920860d1dd073fcc57c7bd33578a04b285b2c655a0b52258d34bee0a20569dca8defb8393e1e5d29 + languageName: node + linkType: hard + "@types/yargs-parser@npm:*": version: 21.0.3 resolution: "@types/yargs-parser@npm:21.0.3" @@ -3500,37 +5670,40 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:^4.0.0": - version: 4.33.0 - resolution: "@typescript-eslint/eslint-plugin@npm:4.33.0" +"@typescript-eslint/eslint-plugin@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/eslint-plugin@npm:7.0.2" dependencies: - "@typescript-eslint/experimental-utils": "npm:4.33.0" - "@typescript-eslint/scope-manager": "npm:4.33.0" - debug: "npm:^4.3.1" - functional-red-black-tree: "npm:^1.0.1" - ignore: "npm:^5.1.8" - regexpp: "npm:^3.1.0" - semver: "npm:^7.3.5" - tsutils: "npm:^3.21.0" + "@eslint-community/regexpp": "npm:^4.5.1" + "@typescript-eslint/scope-manager": "npm:7.0.2" + "@typescript-eslint/type-utils": "npm:7.0.2" + "@typescript-eslint/utils": "npm:7.0.2" + "@typescript-eslint/visitor-keys": "npm:7.0.2" + debug: "npm:^4.3.4" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.2.4" + natural-compare: "npm:^1.4.0" + semver: "npm:^7.5.4" + ts-api-utils: "npm:^1.0.1" peerDependencies: - "@typescript-eslint/parser": ^4.0.0 - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + "@typescript-eslint/parser": ^7.0.0 + eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: c1e1e424e257fa6e5e8b18d7ff77e8a983a761f4acc0cd58ebd31de8ec56c8c472689989cff0290eee41457662a1e664b555cf74bfc1b37bdf8c87ccac2a4663 + checksum: 76727ad48f01c1bb4ef37690e7ed12754930ce3a4bbe5dcd52f24d42f4625fc0b151db8189947f3956b4a09a562eb2da683ff65b57a13a15426eee3b680f80a5 languageName: node linkType: hard "@typescript-eslint/eslint-plugin@npm:^6.8.0": - version: 6.13.1 - resolution: "@typescript-eslint/eslint-plugin@npm:6.13.1" + version: 6.21.0 + resolution: "@typescript-eslint/eslint-plugin@npm:6.21.0" dependencies: "@eslint-community/regexpp": "npm:^4.5.1" - "@typescript-eslint/scope-manager": "npm:6.13.1" - "@typescript-eslint/type-utils": "npm:6.13.1" - "@typescript-eslint/utils": "npm:6.13.1" - "@typescript-eslint/visitor-keys": "npm:6.13.1" + "@typescript-eslint/scope-manager": "npm:6.21.0" + "@typescript-eslint/type-utils": "npm:6.21.0" + "@typescript-eslint/utils": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" debug: "npm:^4.3.4" graphemer: "npm:^1.4.0" ignore: "npm:^5.2.4" @@ -3543,87 +5716,72 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: ccbcbf2a16d985348f46f07c90db06d98878632e7e98eb2fe9275dc489e8a3406bbe002e6d5ff0da88f51a5fe44ea0e942ec35488a3f1939e009f0a43997d34a - languageName: node - linkType: hard - -"@typescript-eslint/experimental-utils@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/experimental-utils@npm:4.33.0" - dependencies: - "@types/json-schema": "npm:^7.0.7" - "@typescript-eslint/scope-manager": "npm:4.33.0" - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/typescript-estree": "npm:4.33.0" - eslint-scope: "npm:^5.1.1" - eslint-utils: "npm:^3.0.0" - peerDependencies: - eslint: "*" - checksum: bb2a48c9df21ef06ccbcd083753b8c51b30a46cde67ab56d278b30ad7868d2e07641e51b6f7fb54437dcb7aff134fac44708e730e2b8f6e43027fefe8629bcb9 + checksum: f911a79ee64d642f814a3b6cdb0d324b5f45d9ef955c5033e78903f626b7239b4aa773e464a38c3e667519066169d983538f2bf8e5d00228af587c9d438fb344 languageName: node linkType: hard -"@typescript-eslint/parser@npm:^4.0.0": - version: 4.33.0 - resolution: "@typescript-eslint/parser@npm:4.33.0" +"@typescript-eslint/parser@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/parser@npm:7.0.2" dependencies: - "@typescript-eslint/scope-manager": "npm:4.33.0" - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/typescript-estree": "npm:4.33.0" - debug: "npm:^4.3.1" + "@typescript-eslint/scope-manager": "npm:7.0.2" + "@typescript-eslint/types": "npm:7.0.2" + "@typescript-eslint/typescript-estree": "npm:7.0.2" + "@typescript-eslint/visitor-keys": "npm:7.0.2" + debug: "npm:^4.3.4" peerDependencies: - eslint: ^5.0.0 || ^6.0.0 || ^7.0.0 + eslint: ^8.56.0 peerDependenciesMeta: typescript: optional: true - checksum: d6f91479b2c0d0ff20ac2dbc7540b28c175fd834a220a4f227209f6c74c55401ac6bd41b2bb4cf40b3ba7761075ccded2019bfc6096c2e4f273bd4ae86c44172 + checksum: acffdbea0bba24398ba8bd1ccf5b59438bc093e41d7a325019383094f39d676b5cf2f5963bfa5e332e54728e5b9e14be3984752ee91da6f0e1a3e0b613422d0e languageName: node linkType: hard "@typescript-eslint/parser@npm:^6.8.0": - version: 6.13.1 - resolution: "@typescript-eslint/parser@npm:6.13.1" + version: 6.21.0 + resolution: "@typescript-eslint/parser@npm:6.21.0" dependencies: - "@typescript-eslint/scope-manager": "npm:6.13.1" - "@typescript-eslint/types": "npm:6.13.1" - "@typescript-eslint/typescript-estree": "npm:6.13.1" - "@typescript-eslint/visitor-keys": "npm:6.13.1" + "@typescript-eslint/scope-manager": "npm:6.21.0" + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/typescript-estree": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 83f67374815f330ba96c2129f616ee1c8af3a7282c91e9645371ce4a9acfc2797df345cc65a34efa3ff0e574ac9422921cdac623a37be21e36e45c46d6de4731 + checksum: a8f99820679decd0d115c0af61903fb1de3b1b5bec412dc72b67670bf636de77ab07f2a68ee65d6da7976039bbf636907f9d5ca546db3f0b98a31ffbc225bc7d languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/scope-manager@npm:4.33.0" +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" dependencies: - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/visitor-keys": "npm:4.33.0" - checksum: 1dfe65777eeb430c1ef778bdad35e6065d4b3075ddb2639d0747d8db93c02eebf6832ba82388a7f80662e0e9f61f1922fe939b53a20889e11fb9f80c4029c6b7 + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" + checksum: eaf868938d811cbbea33e97e44ba7050d2b6892202cea6a9622c486b85ab1cf801979edf78036179a8ba4ac26f1dfdf7fcc83a68c1ff66be0b3a8e9a9989b526 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/scope-manager@npm:6.13.1" +"@typescript-eslint/scope-manager@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/scope-manager@npm:7.0.2" dependencies: - "@typescript-eslint/types": "npm:6.13.1" - "@typescript-eslint/visitor-keys": "npm:6.13.1" - checksum: 2b00f087ba9a9940df4cbc96335312737b3a7744b61528e4949ffd8034067d4c419a7b20beeb4c47d0ed5f52ad82490e89622a0de0e33c4bb6af3ede14c680b8 + "@typescript-eslint/types": "npm:7.0.2" + "@typescript-eslint/visitor-keys": "npm:7.0.2" + checksum: 60241a0dbed7605133b6242d7fc172e8ee649e1033b8a179cebe3e21c60e0c08c12679fd37644cfef57c95a5d75a3927afc9d6365a5f9684c1d043285db23c66 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/type-utils@npm:6.13.1" +"@typescript-eslint/type-utils@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/type-utils@npm:6.21.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:6.13.1" - "@typescript-eslint/utils": "npm:6.13.1" + "@typescript-eslint/typescript-estree": "npm:6.21.0" + "@typescript-eslint/utils": "npm:6.21.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.0.1" peerDependencies: @@ -3631,94 +5789,130 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: c958126cb9d28021ae8e3bb2c11d5f427ab09adff5deaf64927f9769b8ba1f7b561dfb30ac2e69f9ef923183566569500a27a188b534e6641a34e0a6fd144773 + checksum: 7409c97d1c4a4386b488962739c4f1b5b04dc60cf51f8cd88e6b12541f84d84c6b8b67e491a147a2c95f9ec486539bf4519fb9d418411aef6537b9c156468117 languageName: node linkType: hard -"@typescript-eslint/types@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/types@npm:4.33.0" - checksum: 6c94780a589eca7a75ae2b014f320bc412b50794c39ab04889918bb39a40e72584b65c8c0b035330cb0599579afaa3adccee40701f63cf39c0e89299de199d4b +"@typescript-eslint/type-utils@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/type-utils@npm:7.0.2" + dependencies: + "@typescript-eslint/typescript-estree": "npm:7.0.2" + "@typescript-eslint/utils": "npm:7.0.2" + debug: "npm:^4.3.4" + ts-api-utils: "npm:^1.0.1" + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: fa7957aa65cb0d7366c7c9be94e45cc2f1ebe9981cbf393054b505c6d555a01b2a2fe7cd1254d668f30183a275032f909186ce0b9f213f64b776bd7872144a6e languageName: node linkType: hard -"@typescript-eslint/types@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/types@npm:6.13.1" - checksum: 26ea37ec6943859415d683b280e135c20da73281d742aaf123763bf9e10ea0629950422934c4ec3cc77a390a8fa8f33cc4f3914869ffd5af4d1edbbbae834d60 +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 020631d3223bbcff8a0da3efbdf058220a8f48a3de221563996ad1dcc30d6c08dadc3f7608cc08830d21c0d565efd2db19b557b9528921c78aabb605eef2d74d languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/typescript-estree@npm:4.33.0" +"@typescript-eslint/types@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/types@npm:7.0.2" + checksum: 5f95266cc2cd0e6cf1239dcd36b53c7d98b01ba12c61947316f0d879df87b912b4d23f0796324e2ab0fb8780503a338da41a4695fa91d90392b6c6aca5239fa7 + languageName: node + linkType: hard + +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" dependencies: - "@typescript-eslint/types": "npm:4.33.0" - "@typescript-eslint/visitor-keys": "npm:4.33.0" - debug: "npm:^4.3.1" - globby: "npm:^11.0.3" - is-glob: "npm:^4.0.1" - semver: "npm:^7.3.5" - tsutils: "npm:^3.21.0" + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/visitor-keys": "npm:6.21.0" + debug: "npm:^4.3.4" + globby: "npm:^11.1.0" + is-glob: "npm:^4.0.3" + minimatch: "npm:9.0.3" + semver: "npm:^7.5.4" + ts-api-utils: "npm:^1.0.1" peerDependenciesMeta: typescript: optional: true - checksum: 67609a7bdd680136765d103dec4b8afb38a17436e8a5cd830da84f62c6153c3acba561da3b9e2140137b1a0bcbbfc19d4256c692f7072acfebcff88db079e22b + checksum: af1438c60f080045ebb330155a8c9bb90db345d5069cdd5d01b67de502abb7449d6c75500519df829f913a6b3f490ade3e8215279b6bdc63d0fb0ae61034df5f languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/typescript-estree@npm:6.13.1" +"@typescript-eslint/typescript-estree@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/typescript-estree@npm:7.0.2" dependencies: - "@typescript-eslint/types": "npm:6.13.1" - "@typescript-eslint/visitor-keys": "npm:6.13.1" + "@typescript-eslint/types": "npm:7.0.2" + "@typescript-eslint/visitor-keys": "npm:7.0.2" debug: "npm:^4.3.4" globby: "npm:^11.1.0" is-glob: "npm:^4.0.3" + minimatch: "npm:9.0.3" semver: "npm:^7.5.4" ts-api-utils: "npm:^1.0.1" peerDependenciesMeta: typescript: optional: true - checksum: d8aa409464f860f12ddc67ad8d94dcc37dc4da272b1d9d1937b6ccbcf397daa8bb495f409ee5c263053f87a9a0cc7d5ba6926137e5724d4ac6a839d8a481a8c0 + checksum: 2f6795b05fced9f2e0887f6735aa1a0b20516952792e4be13cd94c5e56db8ad013ba27aeb56f89fedff8b7af587f854482f00aac75b418611c74e42169c29aeb languageName: node linkType: hard -"@typescript-eslint/utils@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/utils@npm:6.13.1" +"@typescript-eslint/utils@npm:6.21.0, @typescript-eslint/utils@npm:^6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/utils@npm:6.21.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" "@types/json-schema": "npm:^7.0.12" "@types/semver": "npm:^7.5.0" - "@typescript-eslint/scope-manager": "npm:6.13.1" - "@typescript-eslint/types": "npm:6.13.1" - "@typescript-eslint/typescript-estree": "npm:6.13.1" + "@typescript-eslint/scope-manager": "npm:6.21.0" + "@typescript-eslint/types": "npm:6.21.0" + "@typescript-eslint/typescript-estree": "npm:6.21.0" semver: "npm:^7.5.4" peerDependencies: eslint: ^7.0.0 || ^8.0.0 - checksum: 6706527c6d979ba0a9756394382e945a2de51f54b8193da03ec2f980d479ffca0f58216c90f510b39601d07b37781af4236384f49afc63713662cd309bd43a1f + checksum: ab2df3833b2582d4e5467a484d08942b4f2f7208f8e09d67de510008eb8001a9b7460f2f9ba11c12086fd3cdcac0c626761c7995c2c6b5657d5fa6b82030a32d + languageName: node + linkType: hard + +"@typescript-eslint/utils@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/utils@npm:7.0.2" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.4.0" + "@types/json-schema": "npm:^7.0.12" + "@types/semver": "npm:^7.5.0" + "@typescript-eslint/scope-manager": "npm:7.0.2" + "@typescript-eslint/types": "npm:7.0.2" + "@typescript-eslint/typescript-estree": "npm:7.0.2" + semver: "npm:^7.5.4" + peerDependencies: + eslint: ^8.56.0 + checksum: b4ae9a36393c92b332e99d70219d1ee056271261f7433924db804e5f06d97ca60408b9c7a655afce8a851982e7153243a625d6cc76fea764f767f96c8f3e16da languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:4.33.0": - version: 4.33.0 - resolution: "@typescript-eslint/visitor-keys@npm:4.33.0" +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" dependencies: - "@typescript-eslint/types": "npm:4.33.0" - eslint-visitor-keys: "npm:^2.0.0" - checksum: 95b3904db6113ef365892567d47365e6af3708e6fa905743426036f99e1b7fd4a275facec5d939afecb618369f9d615e379d39f96b8936f469e75507c41c249c + "@typescript-eslint/types": "npm:6.21.0" + eslint-visitor-keys: "npm:^3.4.1" + checksum: 7395f69739cfa1cb83c1fb2fad30afa2a814756367302fb4facd5893eff66abc807e8d8f63eba94ed3b0fe0c1c996ac9a1680bcbf0f83717acedc3f2bb724fbf languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:6.13.1": - version: 6.13.1 - resolution: "@typescript-eslint/visitor-keys@npm:6.13.1" +"@typescript-eslint/visitor-keys@npm:7.0.2": + version: 7.0.2 + resolution: "@typescript-eslint/visitor-keys@npm:7.0.2" dependencies: - "@typescript-eslint/types": "npm:6.13.1" + "@typescript-eslint/types": "npm:7.0.2" eslint-visitor-keys: "npm:^3.4.1" - checksum: 68daf60941fc4824f90480787587c9cbb447eeceac5698dfef2b0c2caa6d3c715f604c2357cc20abb6899be3c3e3ae3b5bbee310faccaab9ea98c8bd9137ec1f + checksum: 4146d1ad6ce9374e6b5a75677fc709816bdc5fe324b1a857405f21dad23bb28c79cfd0555bc2a01c4af1d9e9ee81ff5e29ec41cc9d05b0b1101cc4264e7f21d1 languageName: node linkType: hard @@ -3742,12 +5936,12 @@ __metadata: linkType: hard "@urql/core@npm:>=2.3.6": - version: 4.2.0 - resolution: "@urql/core@npm:4.2.0" + version: 4.2.3 + resolution: "@urql/core@npm:4.2.3" dependencies: "@0no-co/graphql.web": "npm:^1.0.1" wonka: "npm:^6.3.2" - checksum: dbbd500705c2bbf842674016aa69865a90c3d40c1e16034faf6423c9211c37540e975abbf448eae072b7dd38920ed517e8b34ba351f881da1764c22177ca12ed + checksum: 2e2e5f94365c5513c6eb8d996d0b60211ca5ef122bfb7e77a192f63f8f469689ead2b232b835ce47f8127d7c9a5c8083548cac05f3b4be4f01f723dbfb575da0 languageName: node linkType: hard @@ -3775,6 +5969,66 @@ __metadata: languageName: node linkType: hard +"@whatwg-node/cookie-store@npm:^0.0.1": + version: 0.0.1 + resolution: "@whatwg-node/cookie-store@npm:0.0.1" + dependencies: + "@whatwg-node/events": "npm:^0.0.3" + tslib: "npm:^2.3.1" + checksum: dfc7e2ede29d7283b64639b712c3b62b29dffc7e5fec87350078c3586f519764900ac1d1018600211c9fc2789a12393a115c43cdb8438d27870cbaa34b188cdd + languageName: node + linkType: hard + +"@whatwg-node/events@npm:0.0.2": + version: 0.0.2 + resolution: "@whatwg-node/events@npm:0.0.2" + checksum: 79d5da79d5ab1cd28d8bfda7fba6f0a574a9fb9cc7f13fa0ead306a0dcf4ea7058735190ccc7c00c9eb65c3abef109d8db32a525032bb60ffbb374f2e37e78a0 + languageName: node + linkType: hard + +"@whatwg-node/events@npm:^0.0.3": + version: 0.0.3 + resolution: "@whatwg-node/events@npm:0.0.3" + checksum: 87ac0854f84650ce016ccd82a6c087eac1c6204eeb80cf358737ce7757a345e3a4ba19e9b1815b326eb1451d49878785aa9dc426631f4ea47dedbcfc51b56977 + languageName: node + linkType: hard + +"@whatwg-node/fetch@npm:^0.8.0, @whatwg-node/fetch@npm:^0.8.1, @whatwg-node/fetch@npm:^0.8.2, @whatwg-node/fetch@npm:^0.8.3, @whatwg-node/fetch@npm:^0.8.4": + version: 0.8.8 + resolution: "@whatwg-node/fetch@npm:0.8.8" + dependencies: + "@peculiar/webcrypto": "npm:^1.4.0" + "@whatwg-node/node-fetch": "npm:^0.3.6" + busboy: "npm:^1.6.0" + urlpattern-polyfill: "npm:^8.0.0" + web-streams-polyfill: "npm:^3.2.1" + checksum: 37d882bf85764aec7541cda1008099ab4d695971608946ec9b9e40326eedfd4c49507fbcc8765ebe3e9241f4dc9d1e970e0b3501a814d721c40c721d313c5d50 + languageName: node + linkType: hard + +"@whatwg-node/node-fetch@npm:^0.3.6": + version: 0.3.6 + resolution: "@whatwg-node/node-fetch@npm:0.3.6" + dependencies: + "@whatwg-node/events": "npm:^0.0.3" + busboy: "npm:^1.6.0" + fast-querystring: "npm:^1.1.1" + fast-url-parser: "npm:^1.1.3" + tslib: "npm:^2.3.1" + checksum: 49e4fd5e682d1fa1229b2c13c06074c6a633eddbe61be162fd213ddb85d6d27d51554b3cced5f6b7f3be1722a64cca7f5ffe0722d08b3285fe2f289d8d5a045d + languageName: node + linkType: hard + +"@whatwg-node/server@npm:^0.7.3, @whatwg-node/server@npm:^0.7.4": + version: 0.7.7 + resolution: "@whatwg-node/server@npm:0.7.7" + dependencies: + "@whatwg-node/fetch": "npm:^0.8.3" + tslib: "npm:^2.3.1" + checksum: 5bd10ac9414bad7b703088f3fd8539c7dd0fb8ceb252b1e501a7206545ccc2dda8ec9de9e495dd43197c97bc840d7b3d12e06f26ef3f449655f196f6d5c25143 + languageName: node + linkType: hard + "@yarnpkg/lockfile@npm:^1.1.0": version: 1.1.0 resolution: "@yarnpkg/lockfile@npm:1.1.0" @@ -3838,9 +6092,9 @@ __metadata: languageName: node linkType: hard -"abstract-level@npm:^1.0.0, abstract-level@npm:^1.0.2, abstract-level@npm:^1.0.3": - version: 1.0.3 - resolution: "abstract-level@npm:1.0.3" +"abstract-level@npm:^1.0.0, abstract-level@npm:^1.0.2, abstract-level@npm:^1.0.3, abstract-level@npm:^1.0.4": + version: 1.0.4 + resolution: "abstract-level@npm:1.0.4" dependencies: buffer: "npm:^6.0.3" catering: "npm:^2.1.0" @@ -3849,7 +6103,7 @@ __metadata: level-transcoder: "npm:^1.0.1" module-error: "npm:^1.0.1" queue-microtask: "npm:^1.2.3" - checksum: ead09e2aebd45a6aa06175dbda19f08c3fbe2b3fb7637cc15f7c165969fb5ef25a04b743f7e1835fd7cb7f8757ba41a9f43f27b092ab78cab5506f250effc966 + checksum: e89fad8924888b597ca84e6d003a424a670f225fd595ad1f4c2e2d38a5cea3c92877a44f5104cdede1717eb262dd6e7fbf7ef2375569c7395066521170b8d761 languageName: node linkType: hard @@ -3899,7 +6153,7 @@ __metadata: languageName: node linkType: hard -"acorn-jsx@npm:^5.3.1, acorn-jsx@npm:^5.3.2": +"acorn-jsx@npm:^5.3.2": version: 5.3.2 resolution: "acorn-jsx@npm:5.3.2" peerDependencies: @@ -3909,27 +6163,18 @@ __metadata: linkType: hard "acorn-walk@npm:^8.1.1": - version: 8.3.0 - resolution: "acorn-walk@npm:8.3.0" - checksum: 24346e595f507b6e704a60d35f3c5e1aa9891d4fb6a3fc3d856503ab718cc26cabb5e3e1ff0ff8da6ec03d60a8226ebdb602805a94f970e7f797ea3b8b09437f - languageName: node - linkType: hard - -"acorn@npm:^7.4.0": - version: 7.4.1 - resolution: "acorn@npm:7.4.1" - bin: - acorn: bin/acorn - checksum: bd0b2c2b0f334bbee48828ff897c12bd2eb5898d03bf556dcc8942022cec795ac5bb5b6b585e2de687db6231faf07e096b59a361231dd8c9344d5df5f7f0e526 + version: 8.3.2 + resolution: "acorn-walk@npm:8.3.2" + checksum: 7e2a8dad5480df7f872569b9dccff2f3da7e65f5353686b1d6032ab9f4ddf6e3a2cb83a9b52cf50b1497fd522154dda92f0abf7153290cc79cd14721ff121e52 languageName: node linkType: hard -"acorn@npm:^8.4.1, acorn@npm:^8.9.0": - version: 8.11.2 - resolution: "acorn@npm:8.11.2" +"acorn@npm:^8.11.3, acorn@npm:^8.4.1, acorn@npm:^8.9.0": + version: 8.11.3 + resolution: "acorn@npm:8.11.3" bin: acorn: bin/acorn - checksum: a3ed76c761b75ec54b1ec3068fb7f113a182e95aea7f322f65098c2958d232e3d211cb6dac35ff9c647024b63714bc528a26d54a925d1fef2c25585b4c8e4017 + checksum: 3ff155f8812e4a746fee8ecff1f227d527c4c45655bb1fad6347c3cb58e46190598217551b1500f18542d2bbe5c87120cb6927f5a074a59166fbdd9468f0a299 languageName: node linkType: hard @@ -3989,7 +6234,21 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^6.10.0, ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.6": +"ajv-formats@npm:^2.1.1": + version: 2.1.1 + resolution: "ajv-formats@npm:2.1.1" + dependencies: + ajv: "npm:^8.0.0" + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + checksum: e43ba22e91b6a48d96224b83d260d3a3a561b42d391f8d3c6d2c1559f9aa5b253bfb306bc94bbeca1d967c014e15a6efe9a207309e95b3eaae07fcbcdc2af662 + languageName: node + linkType: hard + +"ajv@npm:^6.12.3, ajv@npm:^6.12.4, ajv@npm:^6.12.6": version: 6.12.6 resolution: "ajv@npm:6.12.6" dependencies: @@ -4001,7 +6260,7 @@ __metadata: languageName: node linkType: hard -"ajv@npm:^8.0.1, ajv@npm:^8.11.0": +"ajv@npm:^8.0.0, ajv@npm:^8.0.1, ajv@npm:^8.11.0, ajv@npm:^8.12.0": version: 8.12.0 resolution: "ajv@npm:8.12.0" dependencies: @@ -4014,15 +6273,15 @@ __metadata: linkType: hard "amazon-cognito-identity-js@npm:^6.0.1": - version: 6.3.7 - resolution: "amazon-cognito-identity-js@npm:6.3.7" + version: 6.3.11 + resolution: "amazon-cognito-identity-js@npm:6.3.11" dependencies: "@aws-crypto/sha256-js": "npm:1.2.2" buffer: "npm:4.9.2" fast-base64-decode: "npm:^1.0.0" isomorphic-unfetch: "npm:^3.0.0" js-cookie: "npm:^2.2.1" - checksum: fd4ea95728405c96b477fca7317a2bccb64dd7af1d1ddeb14f4c97986924aa2f7e269b7f20028eeb9cfbd0668c488966f2b393f0102d14e6da19e51b4bce85fd + checksum: 4619e4c19770722ac243c98fb7d4aff35eb0b8f5a2db9ea31a5765f5c54deb7245e316e7e9f633f07d70520f13be157fc90c6139c5f0f2ecc59e5e7d16ee76b1 languageName: node linkType: hard @@ -4033,6 +6292,15 @@ __metadata: languageName: node linkType: hard +"ansi-align@npm:^3.0.0": + version: 3.0.1 + resolution: "ansi-align@npm:3.0.1" + dependencies: + string-width: "npm:^4.1.0" + checksum: ad8b755a253a1bc8234eb341e0cec68a857ab18bf97ba2bda529e86f6e30460416523e0ec58c32e5c21f0ca470d779503244892873a5895dbd0c39c788e82467 + languageName: node + linkType: hard + "ansi-colors@npm:4.1.1": version: 4.1.1 resolution: "ansi-colors@npm:4.1.1" @@ -4040,7 +6308,7 @@ __metadata: languageName: node linkType: hard -"ansi-colors@npm:^4.1.0, ansi-colors@npm:^4.1.1": +"ansi-colors@npm:^4.1.0, ansi-colors@npm:^4.1.1, ansi-colors@npm:^4.1.3": version: 4.1.3 resolution: "ansi-colors@npm:4.1.3" checksum: ec87a2f59902f74e61eada7f6e6fe20094a628dab765cfdbd03c3477599368768cffccdb5d3bb19a1b6c99126783a143b1fee31aab729b31ffe5836c7e5e28b9 @@ -4229,13 +6497,13 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "array-buffer-byte-length@npm:1.0.0" +"array-buffer-byte-length@npm:^1.0.1": + version: 1.0.1 + resolution: "array-buffer-byte-length@npm:1.0.1" dependencies: - call-bind: "npm:^1.0.2" - is-array-buffer: "npm:^3.0.1" - checksum: 12f84f6418b57a954caa41654e5e63e019142a4bbb2c6829ba86d1ba65d31ccfaf1461d1743556fd32b091fac34ff44d9dfbdb001402361c45c373b2c86f5c20 + call-bind: "npm:^1.0.5" + is-array-buffer: "npm:^3.0.4" + checksum: f5cdf54527cd18a3d2852ddf73df79efec03829e7373a8322ef5df2b4ef546fb365c19c71d6b42d641cb6bfe0f1a2f19bc0ece5b533295f86d7c3d522f228917 languageName: node linkType: hard @@ -4275,15 +6543,27 @@ __metadata: linkType: hard "array.prototype.findlast@npm:^1.2.2": - version: 1.2.3 - resolution: "array.prototype.findlast@npm:1.2.3" + version: 1.2.4 + resolution: "array.prototype.findlast@npm:1.2.4" + dependencies: + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.22.3" + es-errors: "npm:^1.3.0" + es-shim-unscopables: "npm:^1.0.2" + checksum: 4b5145a68ebaa00ef3d61de07c6694cad73d60763079f1e7662b948e5a167b5121b0c1e6feae8df1e42ead07c21699e25242b95cd5c48e094fd530b192aa4150 + languageName: node + linkType: hard + +"array.prototype.flat@npm:^1.2.3": + version: 1.3.2 + resolution: "array.prototype.flat@npm:1.3.2" dependencies: call-bind: "npm:^1.0.2" define-properties: "npm:^1.2.0" es-abstract: "npm:^1.22.1" es-shim-unscopables: "npm:^1.0.0" - get-intrinsic: "npm:^1.2.1" - checksum: ace61b1ffc7f323b74626d10a8769ca4fa8888ba23d1bf33f971ec737e01b1c152f9e423d98dc18da4fc4ee840d9e172767d77d6cfc7de4d40477eddf4983a3c + checksum: a578ed836a786efbb6c2db0899ae80781b476200617f65a44846cb1ed8bd8b24c8821b83703375d8af639c689497b7b07277060024b9919db94ac3e10dc8a49b languageName: node linkType: hard @@ -4300,18 +6580,19 @@ __metadata: languageName: node linkType: hard -"arraybuffer.prototype.slice@npm:^1.0.2": - version: 1.0.2 - resolution: "arraybuffer.prototype.slice@npm:1.0.2" +"arraybuffer.prototype.slice@npm:^1.0.3": + version: 1.0.3 + resolution: "arraybuffer.prototype.slice@npm:1.0.3" dependencies: - array-buffer-byte-length: "npm:^1.0.0" - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - es-abstract: "npm:^1.22.1" - get-intrinsic: "npm:^1.2.1" - is-array-buffer: "npm:^3.0.2" + array-buffer-byte-length: "npm:^1.0.1" + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.22.3" + es-errors: "npm:^1.2.1" + get-intrinsic: "npm:^1.2.3" + is-array-buffer: "npm:^3.0.4" is-shared-array-buffer: "npm:^1.0.2" - checksum: 96b6e40e439678ffb7fa266398510074d33c3980fbb475490b69980cca60adec3b0777047ef377068a29862157f83edef42efc64ce48ce38977d04d68de5b7fb + checksum: d32754045bcb2294ade881d45140a5e52bda2321b9e98fa514797b7f0d252c4c5ab0d1edb34112652c62fa6a9398def568da63a4d7544672229afea283358c36 languageName: node linkType: hard @@ -4322,7 +6603,7 @@ __metadata: languageName: node linkType: hard -"asap@npm:~2.0.6": +"asap@npm:^2.0.6, asap@npm:~2.0.3, asap@npm:~2.0.6": version: 2.0.6 resolution: "asap@npm:2.0.6" checksum: c6d5e39fe1f15e4b87677460bd66b66050cd14c772269cee6688824c1410a08ab20254bb6784f9afb75af9144a9f9a7692d49547f4d19d715aeb7c0318f3136d @@ -4350,6 +6631,17 @@ __metadata: languageName: node linkType: hard +"asn1js@npm:^3.0.1, asn1js@npm:^3.0.5": + version: 3.0.5 + resolution: "asn1js@npm:3.0.5" + dependencies: + pvtsutils: "npm:^1.3.2" + pvutils: "npm:^1.1.3" + tslib: "npm:^2.4.0" + checksum: bb8eaf4040c8f49dd475566874986f5976b81bae65a6b5526e2208a13cdca323e69ce297bcd435fdda3eb6933defe888e71974d705b6fcb14f2734a907f8aed4 + languageName: node + linkType: hard + "assert-plus@npm:1.0.0, assert-plus@npm:^1.0.0": version: 1.0.0 resolution: "assert-plus@npm:1.0.0" @@ -4402,11 +6694,11 @@ __metadata: linkType: hard "async-mutex@npm:^0.4.0": - version: 0.4.0 - resolution: "async-mutex@npm:0.4.0" + version: 0.4.1 + resolution: "async-mutex@npm:0.4.1" dependencies: tslib: "npm:^2.4.0" - checksum: 6541695f80c1d6c5acbf3f7f04e8ff0733b3e029312c48d77bb95243fbe21fc5319f45ac3d72ce08551e6df83dc32440285ce9a3ac17bfc5d385ff0cc8ccd62a + checksum: 3c412736c0bc4a9a2cfd948276a8caab8686aa615866a5bd20986e616f8945320acb310058a17afa1b31b8de6f634a78b7ec2217a33d7559b38f68bb85a95854 languageName: node linkType: hard @@ -4481,10 +6773,19 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.5": - version: 1.0.5 - resolution: "available-typed-arrays@npm:1.0.5" - checksum: c4df567ca72d2754a6cbad20088f5f98b1065b3360178169fa9b44ea101af62c0f423fc3854fa820fd6895b6b9171b8386e71558203103ff8fc2ad503fdcc660 +"auto-bind@npm:~4.0.0": + version: 4.0.0 + resolution: "auto-bind@npm:4.0.0" + checksum: 12f70745d081ba990dca028ecfa70de25d4baa9a8b74a5bef3ab293da56cba32ff8276c3ff8e5fe6d9f370547bf3fa71486befbfefe272af7e722c21d0c25530 + languageName: node + linkType: hard + +"available-typed-arrays@npm:^1.0.6, available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: "npm:^1.0.0" + checksum: d07226ef4f87daa01bd0fe80f8f310982e345f372926da2e5296aecc25c41cab440916bbaa4c5e1034b453af3392f67df5961124e4b586df1e99793a1374bdb2 languageName: node linkType: hard @@ -4512,13 +6813,13 @@ __metadata: linkType: hard "axios@npm:^1.4.0, axios@npm:^1.5.1": - version: 1.6.2 - resolution: "axios@npm:1.6.2" + version: 1.6.7 + resolution: "axios@npm:1.6.7" dependencies: - follow-redirects: "npm:^1.15.0" + follow-redirects: "npm:^1.15.4" form-data: "npm:^4.0.0" proxy-from-env: "npm:^1.1.0" - checksum: 9b77e030e85e4f9cbcba7bb52fbff67d6ce906c92d213e0bd932346a50140faf83733bf786f55bd58301bd92f9973885c7b87d6348023e10f7eaf286d0791a1d + checksum: 131bf8e62eee48ca4bd84e6101f211961bf6a21a33b95e5dfb3983d5a2fe50d9fffde0b57668d7ce6f65063d3dc10f2212cbcb554f75cfca99da1c73b210358d languageName: node linkType: hard @@ -4752,6 +7053,13 @@ __metadata: languageName: node linkType: hard +"babel-plugin-syntax-trailing-function-commas@npm:^7.0.0-beta.0": + version: 7.0.0-beta.0 + resolution: "babel-plugin-syntax-trailing-function-commas@npm:7.0.0-beta.0" + checksum: 67e3d6a706637097526b2d3046d3124d3efd3aac28b47af940c2f8df01b8d7ffeb4cdf5648f3b5eac3f098f5b61c4845e306f34301c869e5e14db6ae8b77f699 + languageName: node + linkType: hard + "babel-plugin-transform-async-to-generator@npm:^6.22.0": version: 6.24.1 resolution: "babel-plugin-transform-async-to-generator@npm:6.24.1" @@ -5065,6 +7373,43 @@ __metadata: languageName: node linkType: hard +"babel-preset-fbjs@npm:^3.4.0": + version: 3.4.0 + resolution: "babel-preset-fbjs@npm:3.4.0" + dependencies: + "@babel/plugin-proposal-class-properties": "npm:^7.0.0" + "@babel/plugin-proposal-object-rest-spread": "npm:^7.0.0" + "@babel/plugin-syntax-class-properties": "npm:^7.0.0" + "@babel/plugin-syntax-flow": "npm:^7.0.0" + "@babel/plugin-syntax-jsx": "npm:^7.0.0" + "@babel/plugin-syntax-object-rest-spread": "npm:^7.0.0" + "@babel/plugin-transform-arrow-functions": "npm:^7.0.0" + "@babel/plugin-transform-block-scoped-functions": "npm:^7.0.0" + "@babel/plugin-transform-block-scoping": "npm:^7.0.0" + "@babel/plugin-transform-classes": "npm:^7.0.0" + "@babel/plugin-transform-computed-properties": "npm:^7.0.0" + "@babel/plugin-transform-destructuring": "npm:^7.0.0" + "@babel/plugin-transform-flow-strip-types": "npm:^7.0.0" + "@babel/plugin-transform-for-of": "npm:^7.0.0" + "@babel/plugin-transform-function-name": "npm:^7.0.0" + "@babel/plugin-transform-literals": "npm:^7.0.0" + "@babel/plugin-transform-member-expression-literals": "npm:^7.0.0" + "@babel/plugin-transform-modules-commonjs": "npm:^7.0.0" + "@babel/plugin-transform-object-super": "npm:^7.0.0" + "@babel/plugin-transform-parameters": "npm:^7.0.0" + "@babel/plugin-transform-property-literals": "npm:^7.0.0" + "@babel/plugin-transform-react-display-name": "npm:^7.0.0" + "@babel/plugin-transform-react-jsx": "npm:^7.0.0" + "@babel/plugin-transform-shorthand-properties": "npm:^7.0.0" + "@babel/plugin-transform-spread": "npm:^7.0.0" + "@babel/plugin-transform-template-literals": "npm:^7.0.0" + babel-plugin-syntax-trailing-function-commas: "npm:^7.0.0-beta.0" + peerDependencies: + "@babel/core": ^7.0.0 + checksum: 2be440c0fd7d1df247417be35644cb89f40a300e7fcdc44878b737ec49b04380eff422e4ebdc7bb5efd5ecfef45b634fc5fe11c3a409a50c9084e81083037902 + languageName: node + linkType: hard + "babel-register@npm:^6.26.0": version: 6.26.0 resolution: "babel-register@npm:6.26.0" @@ -5167,6 +7512,13 @@ __metadata: languageName: node linkType: hard +"base-64@npm:^0.1.0": + version: 0.1.0 + resolution: "base-64@npm:0.1.0" + checksum: fe0dcf076e823f04db7ee9b02495be08a91c445fbc6db03cb9913be9680e2fcc0af8b74459041fe08ad16800b1f65a549501d8f08696a8a6d32880789b7de69d + languageName: node + linkType: hard + "base-x@npm:^3.0.2, base-x@npm:^3.0.6, base-x@npm:^3.0.8": version: 3.0.9 resolution: "base-x@npm:3.0.9" @@ -5230,14 +7582,16 @@ __metadata: languageName: node linkType: hard -"big-integer@npm:^1.6.44": - version: 1.6.52 - resolution: "big-integer@npm:1.6.52" - checksum: 9604224b4c2ab3c43c075d92da15863077a9f59e5d4205f4e7e76acd0cd47e8d469ec5e5dba8d9b32aa233951893b29329ca56ac80c20ce094b4a647a66abae0 +"better-path-resolve@npm:1.0.0": + version: 1.0.0 + resolution: "better-path-resolve@npm:1.0.0" + dependencies: + is-windows: "npm:^1.0.0" + checksum: 7335130729d59a14b8e4753fea180ca84e287cccc20cb5f2438a95667abc5810327c414eee7b3c79ed1b5a348a40284ea872958f50caba69432c40405eb0acce languageName: node linkType: hard -"bigint-crypto-utils@npm:^3.0.23": +"bigint-crypto-utils@npm:^3.0.23, bigint-crypto-utils@npm:^3.2.2": version: 3.3.0 resolution: "bigint-crypto-utils@npm:3.3.0" checksum: 7d06fa01d63e8e9513eee629fe8a426993276b1bdca5aefd0eb3188cee7026334d29e801ef6187a5bc6105ebf26e6e79e6fab544a7da769ccf55b913e66d2a14 @@ -5424,12 +7778,19 @@ __metadata: languageName: node linkType: hard -"bplist-parser@npm:^0.2.0": - version: 0.2.0 - resolution: "bplist-parser@npm:0.2.0" +"boxen@npm:^5.1.2": + version: 5.1.2 + resolution: "boxen@npm:5.1.2" dependencies: - big-integer: "npm:^1.6.44" - checksum: ce79c69e0f6efe506281e7c84e3712f7d12978991675b6e3a58a295b16f13ca81aa9b845c335614a545e0af728c8311b6aa3142af76ba1cb616af9bbac5c4a9f + ansi-align: "npm:^3.0.0" + camelcase: "npm:^6.2.0" + chalk: "npm:^4.1.0" + cli-boxes: "npm:^2.2.1" + string-width: "npm:^4.2.2" + type-fest: "npm:^0.20.2" + widest-line: "npm:^3.1.0" + wrap-ansi: "npm:^7.0.0" + checksum: 71f31c2eb3dcacd5fce524ae509e0cc90421752e0bfbd0281fd3352871d106c462a0f810c85f2fdb02f3a9fab2d7a84e9718b4999384d651b76104ebe5d2c024 languageName: node linkType: hard @@ -5479,6 +7840,15 @@ __metadata: languageName: node linkType: hard +"breakword@npm:^1.0.5": + version: 1.0.6 + resolution: "breakword@npm:1.0.6" + dependencies: + wcwidth: "npm:^1.0.1" + checksum: 8bb2e329ee911de098a59d955cb25fad0a16d4f810e3c5ceacfe43ce67cda9117e7e9eafc827234f5429cc0dcaa4d9387e3529cbdcdeb66d1b9e521e28c49bc1 + languageName: node + linkType: hard + "brorand@npm:^1.0.1, brorand@npm:^1.1.0": version: 1.1.0 resolution: "brorand@npm:1.1.0" @@ -5588,6 +7958,20 @@ __metadata: languageName: node linkType: hard +"browserslist@npm:^4.22.2": + version: 4.23.0 + resolution: "browserslist@npm:4.23.0" + dependencies: + caniuse-lite: "npm:^1.0.30001587" + electron-to-chromium: "npm:^1.4.668" + node-releases: "npm:^2.0.14" + update-browserslist-db: "npm:^1.0.13" + bin: + browserslist: cli.js + checksum: 8e9cc154529062128d02a7af4d8adeead83ca1df8cd9ee65a88e2161039f3d68a4d40fea7353cab6bae4c16182dec2fdd9a1cf7dc2a2935498cee1af0e998943 + languageName: node + linkType: hard + "bs58@npm:4.0.1, bs58@npm:^4.0.0": version: 4.0.1 resolution: "bs58@npm:4.0.1" @@ -5617,6 +8001,15 @@ __metadata: languageName: node linkType: hard +"bser@npm:2.1.1": + version: 2.1.1 + resolution: "bser@npm:2.1.1" + dependencies: + node-int64: "npm:^0.4.0" + checksum: 24d8dfb7b6d457d73f32744e678a60cc553e4ec0e9e1a01cf614b44d85c3c87e188d3cc78ef0442ce5032ee6818de20a0162ba1074725c0d08908f62ea979227 + languageName: node + linkType: hard + "buffer-from@npm:^1.0.0": version: 1.1.2 resolution: "buffer-from@npm:1.1.2" @@ -5695,12 +8088,12 @@ __metadata: languageName: node linkType: hard -"bundle-name@npm:^3.0.0": - version: 3.0.0 - resolution: "bundle-name@npm:3.0.0" +"busboy@npm:^1.6.0": + version: 1.6.0 + resolution: "busboy@npm:1.6.0" dependencies: - run-applescript: "npm:^5.0.0" - checksum: 57bc7f8b025d83961b04db2f1eff6a87f2363c2891f3542a4b82471ff8ebb5d484af48e9784fcdb28ef1d48bb01f03d891966dc3ef58758e46ea32d750ce40f8 + streamsearch: "npm:^1.1.0" + checksum: fa7e836a2b82699b6e074393428b91ae579d4f9e21f5ac468e1b459a244341d722d2d22d10920cdd849743dbece6dca11d72de939fb75a7448825cf2babfba1f languageName: node linkType: hard @@ -5738,8 +8131,8 @@ __metadata: linkType: hard "cacache@npm:^18.0.0": - version: 18.0.1 - resolution: "cacache@npm:18.0.1" + version: 18.0.2 + resolution: "cacache@npm:18.0.2" dependencies: "@npmcli/fs": "npm:^3.1.0" fs-minipass: "npm:^3.0.0" @@ -5753,7 +8146,7 @@ __metadata: ssri: "npm:^10.0.0" tar: "npm:^6.1.11" unique-filename: "npm:^3.0.0" - checksum: a31666805a80a8b16ad3f85faf66750275a9175a3480896f4f6d31b5d53ef190484fabd71bdb6d2ea5603c717fbef09f4af03d6a65b525c8ef0afaa44c361866 + checksum: 7992665305cc251a984f4fdbab1449d50e88c635bc43bf2785530c61d239c61b349e5734461baa461caaee65f040ab14e2d58e694f479c0810cffd181ba5eabc languageName: node linkType: hard @@ -5788,6 +8181,28 @@ __metadata: languageName: node linkType: hard +"cacheable-lookup@npm:^7.0.0": + version: 7.0.0 + resolution: "cacheable-lookup@npm:7.0.0" + checksum: 63a9c144c5b45cb5549251e3ea774c04d63063b29e469f7584171d059d3a88f650f47869a974e2d07de62116463d742c287a81a625e791539d987115cb081635 + languageName: node + linkType: hard + +"cacheable-request@npm:^10.2.8": + version: 10.2.14 + resolution: "cacheable-request@npm:10.2.14" + dependencies: + "@types/http-cache-semantics": "npm:^4.0.2" + get-stream: "npm:^6.0.1" + http-cache-semantics: "npm:^4.1.1" + keyv: "npm:^4.5.3" + mimic-response: "npm:^4.0.0" + normalize-url: "npm:^8.0.0" + responselike: "npm:^3.0.0" + checksum: 41b6658db369f20c03128227ecd219ca7ac52a9d24fc0f499cc9aa5d40c097b48b73553504cebd137024d957c0ddb5b67cf3ac1439b136667f3586257763f88d + languageName: node + linkType: hard + "cacheable-request@npm:^6.0.0": version: 6.1.0 resolution: "cacheable-request@npm:6.1.0" @@ -5828,14 +8243,16 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.0, call-bind@npm:^1.0.2, call-bind@npm:^1.0.4, call-bind@npm:^1.0.5, call-bind@npm:~1.0.2": - version: 1.0.5 - resolution: "call-bind@npm:1.0.5" +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7, call-bind@npm:~1.0.2": + version: 1.0.7 + resolution: "call-bind@npm:1.0.7" dependencies: + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" function-bind: "npm:^1.1.2" - get-intrinsic: "npm:^1.2.1" - set-function-length: "npm:^1.1.1" - checksum: a6172c168fd6dacf744fcde745099218056bd755c50415b592655dcd6562157ed29f130f56c3f6db2250f67e4bd62e5c218cdc56d7bfd76e0bda50770fce2d10 + get-intrinsic: "npm:^1.2.4" + set-function-length: "npm:^1.2.1" + checksum: a3ded2e423b8e2a265983dba81c27e125b48eefb2655e7dfab6be597088da3d47c47976c24bc51b8fd9af1061f8f87b4ab78a314f3c77784b2ae2ba535ad8b8d languageName: node linkType: hard @@ -5846,6 +8263,16 @@ __metadata: languageName: node linkType: hard +"camel-case@npm:^4.1.2": + version: 4.1.2 + resolution: "camel-case@npm:4.1.2" + dependencies: + pascal-case: "npm:^3.1.2" + tslib: "npm:^2.0.3" + checksum: bf9eefaee1f20edbed2e9a442a226793bc72336e2b99e5e48c6b7252b6f70b080fc46d8246ab91939e2af91c36cdd422e0af35161e58dd089590f302f8f64c8a + languageName: node + linkType: hard + "camelcase-keys@npm:^6.2.2": version: 6.2.2 resolution: "camelcase-keys@npm:6.2.2" @@ -5864,24 +8291,35 @@ __metadata: languageName: node linkType: hard -"camelcase@npm:^5.3.1": +"camelcase@npm:^5.0.0, camelcase@npm:^5.3.1": version: 5.3.1 resolution: "camelcase@npm:5.3.1" checksum: 92ff9b443bfe8abb15f2b1513ca182d16126359ad4f955ebc83dc4ddcc4ef3fdd2c078bc223f2673dc223488e75c99b16cc4d056624374b799e6a1555cf61b23 languageName: node linkType: hard -"camelcase@npm:^6.0.0": +"camelcase@npm:^6.0.0, camelcase@npm:^6.2.0": version: 6.3.0 resolution: "camelcase@npm:6.3.0" checksum: 0d701658219bd3116d12da3eab31acddb3f9440790c0792e0d398f0a520a6a4058018e546862b6fba89d7ae990efaeb97da71e1913e9ebf5a8b5621a3d55c710 languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30000844": - version: 1.0.30001565 - resolution: "caniuse-lite@npm:1.0.30001565" - checksum: b400e0364651a700e39d59449ca6c65b26e2caceecc4b93ae54a01ed1f62d2a7e1333b1dc640d95fbe620ffa5be38fe4dbacd880cd7a1f42fc72bb8de9a2d0c9 +"caniuse-lite@npm:^1.0.30000844, caniuse-lite@npm:^1.0.30001587": + version: 1.0.30001589 + resolution: "caniuse-lite@npm:1.0.30001589" + checksum: 20debfb949413f603011bc7dacaf050010778bc4f8632c86fafd1bd0c43180c95ae7c31f6c82348f6309e5e221934e327c3607a216e3f09640284acf78cd6d4d + languageName: node + linkType: hard + +"capital-case@npm:^1.0.4": + version: 1.0.4 + resolution: "capital-case@npm:1.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + upper-case-first: "npm:^2.0.2" + checksum: 6a034af73401f6e55d91ea35c190bbf8bda21714d4ea8bb8f1799311d123410a80f0875db4e3236dc3f97d74231ff4bf1c8783f2be13d7733c7d990c57387281 languageName: node linkType: hard @@ -5916,11 +8354,11 @@ __metadata: linkType: hard "cbor@npm:^9.0.0": - version: 9.0.1 - resolution: "cbor@npm:9.0.1" + version: 9.0.2 + resolution: "cbor@npm:9.0.2" dependencies: nofilter: "npm:^3.1.0" - checksum: 7a5148d31f24d47cf1a85b3de8e5b5d7beec60811f8fb448afe960c163c45b4c887be43d617c2d7ced776b485d313ff2828bfde06f99c5c30041912aa4bde444 + checksum: 709d4378067e663107b3d63a02d123a7b33e28946b4c5cc40c102f2f0ba13b072a79adc4369bb87a4e743399fce45deec30463fc84d363ab7cb39192d0fe5f30 languageName: node linkType: hard @@ -5935,9 +8373,9 @@ __metadata: languageName: node linkType: hard -"chai@npm:^4.3.10, chai@npm:^4.3.4": - version: 4.3.10 - resolution: "chai@npm:4.3.10" +"chai@npm:^4.2.0, chai@npm:^4.3.10, chai@npm:^4.3.4": + version: 4.4.1 + resolution: "chai@npm:4.4.1" dependencies: assertion-error: "npm:^1.1.0" check-error: "npm:^1.0.3" @@ -5946,7 +8384,7 @@ __metadata: loupe: "npm:^2.3.6" pathval: "npm:^1.1.1" type-detect: "npm:^4.0.8" - checksum: c887d24f67be6fb554c7ebbde3bb0568697a8833d475e4768296916891ba143f25fc079f6eb34146f3dd5a3279d34c1f387c32c9a6ab288e579f948d9ccf53fe + checksum: 91590a8fe18bd6235dece04ccb2d5b4ecec49984b50924499bdcd7a95c02cb1fd2a689407c19bb854497bde534ef57525cfad6c7fdd2507100fd802fbc2aefbd languageName: node linkType: hard @@ -5963,7 +8401,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:^2.4.1, chalk@npm:^2.4.2": +"chalk@npm:^2.1.0, chalk@npm:^2.4.1, chalk@npm:^2.4.2": version: 2.4.2 resolution: "chalk@npm:2.4.2" dependencies: @@ -5984,6 +8422,62 @@ __metadata: languageName: node linkType: hard +"change-case-all@npm:1.0.14": + version: 1.0.14 + resolution: "change-case-all@npm:1.0.14" + dependencies: + change-case: "npm:^4.1.2" + is-lower-case: "npm:^2.0.2" + is-upper-case: "npm:^2.0.2" + lower-case: "npm:^2.0.2" + lower-case-first: "npm:^2.0.2" + sponge-case: "npm:^1.0.1" + swap-case: "npm:^2.0.2" + title-case: "npm:^3.0.3" + upper-case: "npm:^2.0.2" + upper-case-first: "npm:^2.0.2" + checksum: c2d5fda011b2430f9e503afdca5d8ed48b0e8ee96e38f5530193f8a503317c4a82e6b721c5ea8ef852a2534bdd3d1af25d76e0604b820cd3bc136cf9c179803e + languageName: node + linkType: hard + +"change-case-all@npm:1.0.15": + version: 1.0.15 + resolution: "change-case-all@npm:1.0.15" + dependencies: + change-case: "npm:^4.1.2" + is-lower-case: "npm:^2.0.2" + is-upper-case: "npm:^2.0.2" + lower-case: "npm:^2.0.2" + lower-case-first: "npm:^2.0.2" + sponge-case: "npm:^1.0.1" + swap-case: "npm:^2.0.2" + title-case: "npm:^3.0.3" + upper-case: "npm:^2.0.2" + upper-case-first: "npm:^2.0.2" + checksum: 0de81690de866aa8c477f8b5b08c6f9dbce4a078cffa5f014858f49fda548a9a6524b61f62f2940acce9f1fdcfeef3a7124090684e86e731f55d26c22713e2d7 + languageName: node + linkType: hard + +"change-case@npm:^4.1.2": + version: 4.1.2 + resolution: "change-case@npm:4.1.2" + dependencies: + camel-case: "npm:^4.1.2" + capital-case: "npm:^1.0.4" + constant-case: "npm:^3.0.4" + dot-case: "npm:^3.0.4" + header-case: "npm:^2.0.4" + no-case: "npm:^3.0.4" + param-case: "npm:^3.0.4" + pascal-case: "npm:^3.1.2" + path-case: "npm:^3.0.4" + sentence-case: "npm:^3.0.4" + snake-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: 95a6e48563cd393241ce18470c7310a8a050304a64b63addac487560ab039ce42b099673d1d293cc10652324d92060de11b5d918179fe3b5af2ee521fb03ca58 + languageName: node + linkType: hard + "chardet@npm:^0.7.0": version: 0.7.0 resolution: "chardet@npm:0.7.0" @@ -6016,9 +8510,28 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:3.5.3, chokidar@npm:^3.4.0": - version: 3.5.3 - resolution: "chokidar@npm:3.5.3" +"chokidar@npm:3.5.3": + version: 3.5.3 + resolution: "chokidar@npm:3.5.3" + dependencies: + anymatch: "npm:~3.1.2" + braces: "npm:~3.0.2" + fsevents: "npm:~2.3.2" + glob-parent: "npm:~5.1.2" + is-binary-path: "npm:~2.1.0" + is-glob: "npm:~4.0.1" + normalize-path: "npm:~3.0.0" + readdirp: "npm:~3.6.0" + dependenciesMeta: + fsevents: + optional: true + checksum: 1076953093e0707c882a92c66c0f56ba6187831aa51bb4de878c1fec59ae611a3bf02898f190efec8e77a086b8df61c2b2a3ea324642a0558bdf8ee6c5dc9ca1 + languageName: node + linkType: hard + +"chokidar@npm:^3.4.0": + version: 3.6.0 + resolution: "chokidar@npm:3.6.0" dependencies: anymatch: "npm:~3.1.2" braces: "npm:~3.0.2" @@ -6031,7 +8544,7 @@ __metadata: dependenciesMeta: fsevents: optional: true - checksum: 1076953093e0707c882a92c66c0f56ba6187831aa51bb4de878c1fec59ae611a3bf02898f190efec8e77a086b8df61c2b2a3ea324642a0558bdf8ee6c5dc9ca1 + checksum: 8361dcd013f2ddbe260eacb1f3cb2f2c6f2b0ad118708a343a5ed8158941a39cb8fb1d272e0f389712e74ee90ce8ba864eece9e0e62b9705cb468a2f6d917462 languageName: node linkType: hard @@ -6056,6 +8569,13 @@ __metadata: languageName: node linkType: hard +"ci-info@npm:^3.7.0": + version: 3.9.0 + resolution: "ci-info@npm:3.9.0" + checksum: 6f0109e36e111684291d46123d491bc4e7b7a1934c3a20dea28cba89f1d4a03acd892f5f6a81ed3855c38647e285a150e3c9ba062e38943bef57fee6c1554c3a + languageName: node + linkType: hard + "cids@npm:^0.7.1": version: 0.7.5 resolution: "cids@npm:0.7.5" @@ -6111,8 +8631,8 @@ __metadata: linkType: hard "classic-level@npm:^1.2.0": - version: 1.3.0 - resolution: "classic-level@npm:1.3.0" + version: 1.4.1 + resolution: "classic-level@npm:1.4.1" dependencies: abstract-level: "npm:^1.0.2" catering: "npm:^2.1.0" @@ -6120,7 +8640,7 @@ __metadata: napi-macros: "npm:^2.2.2" node-gyp: "npm:latest" node-gyp-build: "npm:^4.3.0" - checksum: 24b2bd85a4bacba86424903bff6952874bbb8c69ecdbeb77f046e68e67cd1ae4eccfd98af4277538edc6b168db39ca48cd02d172ec3805c3922e4f884732d8ea + checksum: ba769e0b558ab466cef9468f7494b67d8f0139768630ba184d67b33201e67aad274718f3b1b78aaf3c5f5ab4cc526971edf82c7060741031bbad357952e7304d languageName: node linkType: hard @@ -6131,6 +8651,13 @@ __metadata: languageName: node linkType: hard +"cli-boxes@npm:^2.2.1": + version: 2.2.1 + resolution: "cli-boxes@npm:2.2.1" + checksum: 6111352edbb2f62dbc7bfd58f2d534de507afed7f189f13fa894ce5a48badd94b2aa502fda28f1d7dd5f1eb456e7d4033d09a76660013ef50c7f66e7a034f050 + languageName: node + linkType: hard + "cli-cursor@npm:^3.1.0": version: 3.1.0 resolution: "cli-cursor@npm:3.1.0" @@ -6211,6 +8738,17 @@ __metadata: languageName: node linkType: hard +"cliui@npm:^6.0.0": + version: 6.0.0 + resolution: "cliui@npm:6.0.0" + dependencies: + string-width: "npm:^4.2.0" + strip-ansi: "npm:^6.0.0" + wrap-ansi: "npm:^6.2.0" + checksum: 35229b1bb48647e882104cac374c9a18e34bbf0bace0e2cf03000326b6ca3050d6b59545d91e17bfe3705f4a0e2988787aa5cde6331bf5cbbf0164732cef6492 + languageName: node + linkType: hard + "cliui@npm:^7.0.2": version: 7.0.4 resolution: "cliui@npm:7.0.4" @@ -6263,6 +8801,13 @@ __metadata: languageName: node linkType: hard +"coingecko-api@npm:^1.0.10": + version: 1.0.10 + resolution: "coingecko-api@npm:1.0.10" + checksum: 610eba23e63053da72f6690c3371525515218aa04360b9b7c0d992d3b6aeb7314fd946df8b43962ed245bab8ba9ebbde2d2cb57e8a575c73507a61dcf809cf97 + languageName: node + linkType: hard + "collection-visit@npm:^1.0.0": version: 1.0.0 resolution: "collection-visit@npm:1.0.0" @@ -6399,6 +8944,13 @@ __metadata: languageName: node linkType: hard +"commander@npm:^11.1.0": + version: 11.1.0 + resolution: "commander@npm:11.1.0" + checksum: 13cc6ac875e48780250f723fb81c1c1178d35c5decb1abb1b628b3177af08a8554e76b2c0f29de72d69eef7c864d12613272a71fabef8047922bc622ab75a179 + languageName: node + linkType: hard + "commander@npm:^2.15.0": version: 2.20.3 resolution: "commander@npm:2.20.3" @@ -6413,6 +8965,13 @@ __metadata: languageName: node linkType: hard +"common-tags@npm:1.8.2": + version: 1.8.2 + resolution: "common-tags@npm:1.8.2" + checksum: 23efe47ff0a1a7c91489271b3a1e1d2a171c12ec7f9b35b29b2fce51270124aff0ec890087e2bc2182c1cb746e232ab7561aaafe05f1e7452aea733d2bfe3f63 + languageName: node + linkType: hard + "compare-func@npm:^2.0.0": version: 2.0.0 resolution: "compare-func@npm:2.0.0" @@ -6456,12 +9015,40 @@ __metadata: languageName: node linkType: hard +"config-chain@npm:^1.1.11": + version: 1.1.13 + resolution: "config-chain@npm:1.1.13" + dependencies: + ini: "npm:^1.3.4" + proto-list: "npm:~1.2.1" + checksum: 39d1df18739d7088736cc75695e98d7087aea43646351b028dfabd5508d79cf6ef4c5bcd90471f52cd87ae470d1c5490c0a8c1a292fbe6ee9ff688061ea0963e + languageName: node + linkType: hard + +"consola@npm:^2.15.0": + version: 2.15.3 + resolution: "consola@npm:2.15.3" + checksum: 34a337e6b4a1349ee4d7b4c568484344418da8fdb829d7d71bfefcd724f608f273987633b6eef465e8de510929907a092e13cb7a28a5d3acb3be446fcc79fd5e + languageName: node + linkType: hard + "console-table-printer@npm:^2.11.1, console-table-printer@npm:^2.9.0": - version: 2.11.2 - resolution: "console-table-printer@npm:2.11.2" + version: 2.12.0 + resolution: "console-table-printer@npm:2.12.0" dependencies: simple-wcswidth: "npm:^1.0.1" - checksum: 03d46563591395f54fb756a7793b289d1f162eac8dfabf52dbb31b71bf5745e11e6d002da92c38e25b94bb2f5302bae707693ebbfbe406109f21e9e486ddecfb + checksum: 122ac2c7be70b2554acb3be9f0b5c4224113307d30a28c20264eb65ae33ef5522986dd216422697297ee740f5ba293910d03dd969bdceee5a61aa0843fa6b201 + languageName: node + linkType: hard + +"constant-case@npm:^3.0.4": + version: 3.0.4 + resolution: "constant-case@npm:3.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + upper-case: "npm:^2.0.2" + checksum: 91d54f18341fcc491ae66d1086642b0cc564be3e08984d7b7042f8b0a721c8115922f7f11d6a09f13ed96ff326eabae11f9d1eb0335fa9d8b6e39e4df096010e languageName: node linkType: hard @@ -6531,6 +9118,13 @@ __metadata: languageName: node linkType: hard +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b + languageName: node + linkType: hard + "cookie-signature@npm:1.0.6": version: 1.0.6 resolution: "cookie-signature@npm:1.0.6" @@ -6567,9 +9161,9 @@ __metadata: linkType: hard "core-js-pure@npm:^3.0.1": - version: 3.33.3 - resolution: "core-js-pure@npm:3.33.3" - checksum: 97cf39cc013f6a4f77700762de36b495228b3c087fc04b61e86bfbfb475595529966cabbcf37e738e3a468c486e815c85118d120cc6fc4960da08a14caf69826 + version: 3.36.0 + resolution: "core-js-pure@npm:3.36.0" + checksum: 1c5ecb37451bcebaa449e36285d27c4c79d5ff24b8bfd44491ce661cfc12b5c56471c847d306d21a56894338d00abea4993a6f8e07c71d4e887d1f71e410d22e languageName: node linkType: hard @@ -6630,7 +9224,7 @@ __metadata: languageName: node linkType: hard -"cosmiconfig@npm:^8.0.0, cosmiconfig@npm:^8.3.6": +"cosmiconfig@npm:^8.0.0, cosmiconfig@npm:^8.1.3, cosmiconfig@npm:^8.3.6": version: 8.3.6 resolution: "cosmiconfig@npm:8.3.6" dependencies: @@ -6728,7 +9322,7 @@ __metadata: languageName: node linkType: hard -"cross-fetch@npm:^3.1.4": +"cross-fetch@npm:^3.1.4, cross-fetch@npm:^3.1.5": version: 3.1.8 resolution: "cross-fetch@npm:3.1.8" dependencies: @@ -6737,6 +9331,17 @@ __metadata: languageName: node linkType: hard +"cross-spawn@npm:^5.1.0": + version: 5.1.0 + resolution: "cross-spawn@npm:5.1.0" + dependencies: + lru-cache: "npm:^4.0.1" + shebang-command: "npm:^1.2.0" + which: "npm:^1.2.9" + checksum: 1918621fddb9f8c61e02118b2dbf81f611ccd1544ceaca0d026525341832b8511ce2504c60f935dbc06b35e5ef156fe8c1e72708c27dd486f034e9c0e1e07201 + languageName: node + linkType: hard + "cross-spawn@npm:^6.0.5": version: 6.0.5 resolution: "cross-spawn@npm:6.0.5" @@ -6787,6 +9392,39 @@ __metadata: languageName: node linkType: hard +"csv-generate@npm:^3.4.3": + version: 3.4.3 + resolution: "csv-generate@npm:3.4.3" + checksum: 196afb16ec5e72f8a77a9742a9c5640868768e114ca5e0dcc22d4e6f9bfacb552432a2ca8658429b494d602d8fcc16f7efdad0ad45b7108fbd3f936074f43622 + languageName: node + linkType: hard + +"csv-parse@npm:^4.16.3": + version: 4.16.3 + resolution: "csv-parse@npm:4.16.3" + checksum: 40771fda105b10c3e44551fa4dbeab462315400deb572f2918c19d5848addd95ea3479aaaeaaf3bbd9235593a6d798dd90b9e6ba5c4ce570979bafc4bb1ba5f0 + languageName: node + linkType: hard + +"csv-stringify@npm:^5.6.5": + version: 5.6.5 + resolution: "csv-stringify@npm:5.6.5" + checksum: 125194dcf24a94e9c03eb53b3bc4b79cc6611747e73fe3c0e8a342a9f385caeb4e88c0827e89a4c508b45ea99bdc64a339b487f80048a50fabcbb3a7d87ea1a9 + languageName: node + linkType: hard + +"csv@npm:^5.5.3": + version: 5.5.3 + resolution: "csv@npm:5.5.3" + dependencies: + csv-generate: "npm:^3.4.3" + csv-parse: "npm:^4.16.3" + csv-stringify: "npm:^5.6.5" + stream-transform: "npm:^2.1.3" + checksum: 282720e1f9f1a332c0ff2c4d48d845eab2a60c23087c974eb6ffc4d907f40c053ae0f8458819d670ad2986ec25359e57dbccc0fa3370cd5d92e7d3143e345f95 + languageName: node + linkType: hard + "d@npm:1, d@npm:^1.0.1": version: 1.0.1 resolution: "d@npm:1.0.1" @@ -6813,6 +9451,20 @@ __metadata: languageName: node linkType: hard +"dataloader@npm:2.2.2, dataloader@npm:^2.2.2": + version: 2.2.2 + resolution: "dataloader@npm:2.2.2" + checksum: 125ec69f821478cf7c6b4360095db6cab939fe57876a0d2060c428091a8deee7152345189923b71a6afa694aaec463779f34b585317164016fd6f54f52cd94ba + languageName: node + linkType: hard + +"dayjs@npm:1.11.7": + version: 1.11.7 + resolution: "dayjs@npm:1.11.7" + checksum: 41a54853c8b8bf0fa94a5559eec98b3e4d11b31af81a9558a159d40adeaafb1f3414e8c41a4e3277281d97687d8252f400015e1f715b47f8c24d88a9ebd43626 + languageName: node + linkType: hard + "death@npm:^1.1.0": version: 1.1.0 resolution: "death@npm:1.1.0" @@ -6838,7 +9490,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.0.1, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:4.3.4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.4 resolution: "debug@npm:4.3.4" dependencies: @@ -6869,7 +9521,7 @@ __metadata: languageName: node linkType: hard -"decamelize@npm:^1.1.0, decamelize@npm:^1.1.1": +"decamelize@npm:^1.1.0, decamelize@npm:^1.1.1, decamelize@npm:^1.2.0": version: 1.2.0 resolution: "decamelize@npm:1.2.0" checksum: 85c39fe8fbf0482d4a1e224ef0119db5c1897f8503bcef8b826adff7a1b11414972f6fef2d7dec2ee0b4be3863cf64ac1439137ae9e6af23a3d8dcbe26a5b4b2 @@ -6938,6 +9590,13 @@ __metadata: languageName: node linkType: hard +"deep-extend@npm:^0.6.0": + version: 0.6.0 + resolution: "deep-extend@npm:0.6.0" + checksum: 1c6b0abcdb901e13a44c7d699116d3d4279fdb261983122a3783e7273844d5f2537dc2e1c454a23fcf645917f93fbf8d07101c1d03c015a87faa662755212566 + languageName: node + linkType: hard + "deep-is@npm:^0.1.3, deep-is@npm:~0.1.3": version: 0.1.4 resolution: "deep-is@npm:0.1.4" @@ -6945,28 +9604,6 @@ __metadata: languageName: node linkType: hard -"default-browser-id@npm:^3.0.0": - version: 3.0.0 - resolution: "default-browser-id@npm:3.0.0" - dependencies: - bplist-parser: "npm:^0.2.0" - untildify: "npm:^4.0.0" - checksum: 8db3ab882eb3e1e8b59d84c8641320e6c66d8eeb17eb4bb848b7dd549b1e6fd313988e4a13542e95fbaeff03f6e9dedc5ad191ad4df7996187753eb0d45c00b7 - languageName: node - linkType: hard - -"default-browser@npm:^4.0.0": - version: 4.0.0 - resolution: "default-browser@npm:4.0.0" - dependencies: - bundle-name: "npm:^3.0.0" - default-browser-id: "npm:^3.0.0" - execa: "npm:^7.1.1" - titleize: "npm:^3.0.0" - checksum: 7c8848badc139ecf9d878e562bc4e7ab4301e51ba120b24d8dcb14739c30152115cc612065ac3ab73c02aace4afa29db5a044257b2f0cf234f16e3a58f6c925e - languageName: node - linkType: hard - "defaults@npm:^1.0.3": version: 1.0.4 resolution: "defaults@npm:1.0.4" @@ -7009,25 +9646,18 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1": - version: 1.1.1 - resolution: "define-data-property@npm:1.1.1" +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.1, define-data-property@npm:^1.1.2, define-data-property@npm:^1.1.4": + version: 1.1.4 + resolution: "define-data-property@npm:1.1.4" dependencies: - get-intrinsic: "npm:^1.2.1" + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.0" - checksum: 77ef6e0bceb515e05b5913ab635a84d537cee84f8a7c37c77fdcb31fc5b80f6dbe81b33375e4b67d96aa04e6a0d8d4ea099e431d83f089af8d93adfb584bcb94 - languageName: node - linkType: hard - -"define-lazy-prop@npm:^3.0.0": - version: 3.0.0 - resolution: "define-lazy-prop@npm:3.0.0" - checksum: 5ab0b2bf3fa58b3a443140bbd4cd3db1f91b985cc8a246d330b9ac3fc0b6a325a6d82bddc0b055123d745b3f9931afeea74a5ec545439a1630b9c8512b0eeb49 + checksum: dea0606d1483eb9db8d930d4eac62ca0fa16738b0b3e07046cddfacf7d8c868bbe13fa0cb263eb91c7d0d527960dc3f2f2471a69ed7816210307f6744fe62e37 languageName: node linkType: hard -"define-properties@npm:^1.1.3, define-properties@npm:^1.1.4, define-properties@npm:^1.2.0": +"define-properties@npm:^1.1.3, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -7115,6 +9745,13 @@ __metadata: languageName: node linkType: hard +"dependency-graph@npm:0.11.0, dependency-graph@npm:^0.11.0": + version: 0.11.0 + resolution: "dependency-graph@npm:0.11.0" + checksum: 9e6968d1534fdb502f7f3a25a3819b499f9d60f8389193950ed0b4d1618f1341b36b5d039f2cee256cfe10c9e8198ace16b271e370df06a93fac206e81602e7c + languageName: node + linkType: hard + "des.js@npm:^1.0.0": version: 1.1.0 resolution: "des.js@npm:1.1.0" @@ -7148,6 +9785,13 @@ __metadata: languageName: node linkType: hard +"detect-indent@npm:^6.0.0": + version: 6.1.0 + resolution: "detect-indent@npm:6.1.0" + checksum: dd83cdeda9af219cf77f5e9a0dc31d828c045337386cfb55ce04fad94ba872ee7957336834154f7647b89b899c3c7acc977c57a79b7c776b506240993f97acc7 + languageName: node + linkType: hard + "detect-port@npm:^1.3.0": version: 1.5.1 resolution: "detect-port@npm:1.5.1" @@ -7176,9 +9820,9 @@ __metadata: linkType: hard "diff@npm:^5.0.0": - version: 5.1.0 - resolution: "diff@npm:5.1.0" - checksum: 77a0d9beb9ed54796154ac2511872288432124ac90a1cabb1878783c9b4d81f1847f3b746a0630b1e836181461d2c76e1e6b95559bef86ed16294d114862e364 + version: 5.2.0 + resolution: "diff@npm:5.2.0" + checksum: aed0941f206fe261ecb258dc8d0ceea8abbde3ace5827518ff8d302f0fc9cc81ce116c4d8f379151171336caf0516b79e01abdc1ed1201b6440d895a66689eb4 languageName: node linkType: hard @@ -7213,6 +9857,16 @@ __metadata: languageName: node linkType: hard +"dnscache@npm:^1.0.2": + version: 1.0.2 + resolution: "dnscache@npm:1.0.2" + dependencies: + asap: "npm:^2.0.6" + lodash.clone: "npm:^4.5.0" + checksum: d152a331a1ea8bef6cdfdb447ff5ecc393f1e54d801374ff0f5195119a91096968a9f2ddcc37df8e12a18b5fea8cd8f7d260b67fe6cd83a169d47a80b03770f9 + languageName: node + linkType: hard + "doctrine@npm:^3.0.0": version: 3.0.0 resolution: "doctrine@npm:3.0.0" @@ -7229,6 +9883,16 @@ __metadata: languageName: node linkType: hard +"dot-case@npm:^3.0.4": + version: 3.0.4 + resolution: "dot-case@npm:3.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: 5b859ea65097a7ea870e2c91b5768b72ddf7fa947223fd29e167bcdff58fe731d941c48e47a38ec8aa8e43044c8fbd15cd8fa21689a526bc34b6548197cd5b05 + languageName: node + linkType: hard + "dot-prop@npm:^5.1.0": version: 5.3.0 resolution: "dot-prop@npm:5.3.0" @@ -7238,10 +9902,10 @@ __metadata: languageName: node linkType: hard -"dotenv@npm:*": - version: 16.3.1 - resolution: "dotenv@npm:16.3.1" - checksum: b95ff1bbe624ead85a3cd70dbd827e8e06d5f05f716f2d0cbc476532d54c7c9469c3bc4dd93ea519f6ad711cb522c00ac9a62b6eb340d5affae8008facc3fbd7 +"dotenv@npm:*, dotenv@npm:^16.0.0, dotenv@npm:^16.0.3": + version: 16.4.5 + resolution: "dotenv@npm:16.4.5" + checksum: 48d92870076832af0418b13acd6e5a5a3e83bb00df690d9812e94b24aff62b88ade955ac99a05501305b8dc8f1b0ee7638b18493deb6fe93d680e5220936292f languageName: node linkType: hard @@ -7270,6 +9934,13 @@ __metadata: languageName: node linkType: hard +"dset@npm:^3.1.1, dset@npm:^3.1.2": + version: 3.1.3 + resolution: "dset@npm:3.1.3" + checksum: b1ff68f1f42af373baa85b00b04d89094cd0d7f74f94bd11364cba575f2762ed52a0a0503bbfcc92eccd07c6d55426813c8a7a6cfa020338eaea1f4edfd332c2 + languageName: node + linkType: hard + "duplexer3@npm:^0.1.4": version: 0.1.5 resolution: "duplexer3@npm:0.1.5" @@ -7313,10 +9984,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.3.47": - version: 1.4.596 - resolution: "electron-to-chromium@npm:1.4.596" - checksum: 6e05fdbe0a77beda4eaad646c83143ccf4dcec5b15da7dc641bbd872ef62acff4cb31e1febf4bafdbe8e1f61720c2ff738690acce0b8dac980a331802633befd +"electron-to-chromium@npm:^1.3.47, electron-to-chromium@npm:^1.4.668": + version: 1.4.681 + resolution: "electron-to-chromium@npm:1.4.681" + checksum: 5b2558dfb8bb82c20fb5fa1d9bbe06a3add47431dc3e1e4815e997be6ad387787047d9e534ed96839a9e7012520a5281c865158b09db41d10c029af003f05f94 languageName: node linkType: hard @@ -7335,13 +10006,6 @@ __metadata: languageName: node linkType: hard -"emoji-regex@npm:^10.0.0": - version: 10.3.0 - resolution: "emoji-regex@npm:10.3.0" - checksum: b4838e8dcdceb44cf47f59abe352c25ff4fe7857acaf5fb51097c427f6f75b44d052eb907a7a3b86f86bc4eae3a93f5c2b7460abe79c407307e6212d65c91163 - languageName: node - linkType: hard - "emoji-regex@npm:^8.0.0": version: 8.0.0 resolution: "emoji-regex@npm:8.0.0" @@ -7363,6 +10027,13 @@ __metadata: languageName: node linkType: hard +"encode-utf8@npm:^1.0.2": + version: 1.0.3 + resolution: "encode-utf8@npm:1.0.3" + checksum: 6b3458b73e868113d31099d7508514a5c627d8e16d1e0542d1b4e3652299b8f1f590c468e2b9dcdf1b4021ee961f31839d0be9d70a7f2a8a043c63b63c9b3a88 + languageName: node + linkType: hard + "encodeurl@npm:~1.0.2": version: 1.0.2 resolution: "encodeurl@npm:1.0.2" @@ -7401,7 +10072,7 @@ __metadata: languageName: node linkType: hard -"enquirer@npm:^2.3.0, enquirer@npm:^2.3.5, enquirer@npm:^2.3.6": +"enquirer@npm:^2.3.0, enquirer@npm:^2.3.6": version: 2.4.1 resolution: "enquirer@npm:2.4.1" dependencies: @@ -7452,50 +10123,52 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.22.1": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" +"es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3": + version: 1.22.4 + resolution: "es-abstract@npm:1.22.4" dependencies: - array-buffer-byte-length: "npm:^1.0.0" - arraybuffer.prototype.slice: "npm:^1.0.2" - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.5" - es-set-tostringtag: "npm:^2.0.1" + array-buffer-byte-length: "npm:^1.0.1" + arraybuffer.prototype.slice: "npm:^1.0.3" + available-typed-arrays: "npm:^1.0.6" + call-bind: "npm:^1.0.7" + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + es-set-tostringtag: "npm:^2.0.2" es-to-primitive: "npm:^1.2.1" function.prototype.name: "npm:^1.1.6" - get-intrinsic: "npm:^1.2.2" - get-symbol-description: "npm:^1.0.0" + get-intrinsic: "npm:^1.2.4" + get-symbol-description: "npm:^1.0.2" globalthis: "npm:^1.0.3" gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.0" + has-property-descriptors: "npm:^1.0.2" has-proto: "npm:^1.0.1" has-symbols: "npm:^1.0.3" - hasown: "npm:^2.0.0" - internal-slot: "npm:^1.0.5" - is-array-buffer: "npm:^3.0.2" + hasown: "npm:^2.0.1" + internal-slot: "npm:^1.0.7" + is-array-buffer: "npm:^3.0.4" is-callable: "npm:^1.2.7" is-negative-zero: "npm:^2.0.2" is-regex: "npm:^1.1.4" is-shared-array-buffer: "npm:^1.0.2" is-string: "npm:^1.0.7" - is-typed-array: "npm:^1.1.12" + is-typed-array: "npm:^1.1.13" is-weakref: "npm:^1.0.2" object-inspect: "npm:^1.13.1" object-keys: "npm:^1.1.1" - object.assign: "npm:^4.1.4" - regexp.prototype.flags: "npm:^1.5.1" - safe-array-concat: "npm:^1.0.1" - safe-regex-test: "npm:^1.0.0" + object.assign: "npm:^4.1.5" + regexp.prototype.flags: "npm:^1.5.2" + safe-array-concat: "npm:^1.1.0" + safe-regex-test: "npm:^1.0.3" string.prototype.trim: "npm:^1.2.8" string.prototype.trimend: "npm:^1.0.7" string.prototype.trimstart: "npm:^1.0.7" - typed-array-buffer: "npm:^1.0.0" + typed-array-buffer: "npm:^1.0.1" typed-array-byte-length: "npm:^1.0.0" typed-array-byte-offset: "npm:^1.0.0" typed-array-length: "npm:^1.0.4" unbox-primitive: "npm:^1.0.2" - which-typed-array: "npm:^1.1.13" - checksum: da31ec43b1c8eb47ba8a17693cac143682a1078b6c3cd883ce0e2062f135f532e93d873694ef439670e1f6ca03195118f43567ba6f33fb0d6c7daae750090236 + which-typed-array: "npm:^1.1.14" + checksum: dc332c3a010c5e7b77b7ea8a4532ac455fa02e7bcabf996a47447165bafa72d0d99967407d0cf5dbbb5fbbf87f53cd8b706608ec70953523b8cd2b831b9a9d64 languageName: node linkType: hard @@ -7506,18 +10179,34 @@ __metadata: languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.1": - version: 2.0.2 - resolution: "es-set-tostringtag@npm:2.0.2" +"es-define-property@npm:^1.0.0": + version: 1.0.0 + resolution: "es-define-property@npm:1.0.0" dependencies: - get-intrinsic: "npm:^1.2.2" - has-tostringtag: "npm:^1.0.0" - hasown: "npm:^2.0.0" - checksum: 176d6bd1be31dd0145dcceee62bb78d4a5db7f81db437615a18308a6f62bcffe45c15081278413455e8cf0aad4ea99079de66f8de389605942dfdacbad74c2d5 + get-intrinsic: "npm:^1.2.4" + checksum: 6bf3191feb7ea2ebda48b577f69bdfac7a2b3c9bcf97307f55fd6ef1bbca0b49f0c219a935aca506c993d8c5d8bddd937766cb760cd5e5a1071351f2df9f9aa4 + languageName: node + linkType: hard + +"es-errors@npm:^1.2.1, es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 + languageName: node + linkType: hard + +"es-set-tostringtag@npm:^2.0.2": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" + dependencies: + get-intrinsic: "npm:^1.2.4" + has-tostringtag: "npm:^1.0.2" + hasown: "npm:^2.0.1" + checksum: f22aff1585eb33569c326323f0b0d175844a1f11618b86e193b386f8be0ea9474cfbe46df39c45d959f7aa8f6c06985dc51dd6bce5401645ec5a74c4ceaa836a languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0": +"es-shim-unscopables@npm:^1.0.0, es-shim-unscopables@npm:^1.0.2": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" dependencies: @@ -7537,14 +10226,15 @@ __metadata: languageName: node linkType: hard -"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50": - version: 0.10.62 - resolution: "es5-ext@npm:0.10.62" +"es5-ext@npm:^0.10.35, es5-ext@npm:^0.10.50, es5-ext@npm:^0.10.62, es5-ext@npm:~0.10.14": + version: 0.10.63 + resolution: "es5-ext@npm:0.10.63" dependencies: es6-iterator: "npm:^2.0.3" es6-symbol: "npm:^3.1.3" + esniff: "npm:^2.0.1" next-tick: "npm:^1.1.0" - checksum: 72dfbec5e4bce24754be9f2c2a1c67c01de3fe000103c115f52891f6a51f44a59674c40a1f6bd2390fcd43987746dccb76efafea91c7bb6295bdca8d63ba3db4 + checksum: 1f20f9c73dc43cca9f1aa6908062f0a3d0bf3cee229a11a2cda6d4eca83583ceeb9b59ad36e951aa6e41ddd06d81aafac9a01de3d38a76b86f598a69ad0456bd languageName: node linkType: hard @@ -7577,9 +10267,9 @@ __metadata: linkType: hard "escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: afd02e6ca91ffa813e1108b5e7756566173d6bc0d1eb951cb44d6b21702ec17c1cf116cfe75d4a2b02e05acb0b808a7a9387d0d1ca5cf9c04ad03a8445c3e46d + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 6b4adafecd0682f3aa1cd1106b8fff30e492c7015b178bc81b2d2f75106dabea6c6d6e8508fc491bd58e597c74abb0e8e2368f943ecb9393d4162e3c2f3cf287 languageName: node linkType: hard @@ -7623,34 +10313,33 @@ __metadata: languageName: node linkType: hard -"eslint-config-prettier@npm:^8.3.0": - version: 8.10.0 - resolution: "eslint-config-prettier@npm:8.10.0" - peerDependencies: - eslint: ">=7.0.0" - bin: - eslint-config-prettier: bin/cli.js - checksum: 19f8c497d9bdc111a17a61b25ded97217be3755bbc4714477dfe535ed539dddcaf42ef5cf8bb97908b058260cf89a3d7c565cb0be31096cbcd39f4c2fa5fe43c - languageName: node - linkType: hard - "eslint-config-prettier@npm:^9.0.0": - version: 9.0.0 - resolution: "eslint-config-prettier@npm:9.0.0" + version: 9.1.0 + resolution: "eslint-config-prettier@npm:9.1.0" peerDependencies: eslint: ">=7.0.0" bin: eslint-config-prettier: bin/cli.js - checksum: bc1f661915845c631824178942e5d02f858fe6d0ea796f0050d63e0f681927b92696e81139dd04714c08c3e7de580fd079c66162e40070155ba79eaee78ab5d0 + checksum: 6d332694b36bc9ac6fdb18d3ca2f6ac42afa2ad61f0493e89226950a7091e38981b66bac2b47ba39d15b73fff2cd32c78b850a9cf9eed9ca9a96bfb2f3a2f10d languageName: node linkType: hard -"eslint-plugin-no-only-tests@npm:^2.4.0": - version: 2.6.0 - resolution: "eslint-plugin-no-only-tests@npm:2.6.0" - checksum: 23e0a65f7483fac71073535a12567dab1a32fa2fb1e993cac60bbb93409f669ee98a2a296c3a4f862aefa76850a1576c17511cb21e6e2470a58a8c6f9b6f3043 - languageName: node - linkType: hard +"eslint-graph-config@workspace:^, eslint-graph-config@workspace:^0.0.1, eslint-graph-config@workspace:packages/eslint-graph-config": + version: 0.0.0-use.local + resolution: "eslint-graph-config@workspace:packages/eslint-graph-config" + dependencies: + "@stylistic/eslint-plugin": "npm:^1.6.2" + "@types/eslint__js": "npm:^8.42.3" + "@types/node": "npm:^20.11.19" + eslint: "npm:^8.56.0" + eslint-plugin-no-only-tests: "npm:^3.1.0" + eslint-plugin-no-secrets: "npm:^0.8.9" + typescript: "npm:^5.3.3" + typescript-eslint: "npm:^7.0.2" + peerDependencies: + eslint: ^8.56.0 + languageName: unknown + linkType: soft "eslint-plugin-no-only-tests@npm:^3.1.0": version: 3.1.0 @@ -7659,47 +10348,32 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-prettier@npm:^3.4.0": - version: 3.4.1 - resolution: "eslint-plugin-prettier@npm:3.4.1" - dependencies: - prettier-linter-helpers: "npm:^1.0.0" +"eslint-plugin-no-secrets@npm:^0.8.9": + version: 0.8.9 + resolution: "eslint-plugin-no-secrets@npm:0.8.9" peerDependencies: - eslint: ">=5.0.0" - prettier: ">=1.13.0" - peerDependenciesMeta: - eslint-config-prettier: - optional: true - checksum: b2599dd22b5b0d2e3baffc94ba55a33ed525d642125d657fbc8511a2458146bdcc2bc810418713bb0049e37765def92b51213a4467984f4c758807bea224d0c5 + eslint: ">=3.0.0" + checksum: d1b630bf87873b6d5ad009aed889ce3972815b2e8d62b3fdbc2cc21d03b759b9548f4655f52afb6e3014228f75840d59b4426758986e76b7dba245adbf560bda languageName: node linkType: hard "eslint-plugin-prettier@npm:^5.0.1": - version: 5.0.1 - resolution: "eslint-plugin-prettier@npm:5.0.1" + version: 5.1.3 + resolution: "eslint-plugin-prettier@npm:5.1.3" dependencies: prettier-linter-helpers: "npm:^1.0.0" - synckit: "npm:^0.8.5" + synckit: "npm:^0.8.6" peerDependencies: "@types/eslint": ">=8.0.0" eslint: ">=8.0.0" + eslint-config-prettier: "*" prettier: ">=3.0.0" peerDependenciesMeta: "@types/eslint": optional: true eslint-config-prettier: optional: true - checksum: 08e2c7bed93d9f7c86e9aa0bd4f5cc51f65233a446ddfda11e821f12819e1e4be62cfbc2a4e17169c76fded1c4de7371e37e5f2525e81695decaf6c652a41fb0 - languageName: node - linkType: hard - -"eslint-scope@npm:^5.1.1": - version: 5.1.1 - resolution: "eslint-scope@npm:5.1.1" - dependencies: - esrecurse: "npm:^4.3.0" - estraverse: "npm:^4.1.1" - checksum: d30ef9dc1c1cbdece34db1539a4933fe3f9b14e1ffb27ecc85987902ee663ad7c9473bbd49a9a03195a373741e62e2f807c4938992e019b511993d163450e70a + checksum: f45d5fc1fcfec6b0cf038a7a65ddd10a25df4fe3f9e1f6b7f0d5100e66f046a26a2492e69ee765dddf461b93c114cf2e1eb18d4970aafa6f385448985c136e09 languageName: node linkType: hard @@ -7713,40 +10387,6 @@ __metadata: languageName: node linkType: hard -"eslint-utils@npm:^2.1.0": - version: 2.1.0 - resolution: "eslint-utils@npm:2.1.0" - dependencies: - eslint-visitor-keys: "npm:^1.1.0" - checksum: 69521c5d6569384b24093125d037ba238d3d6e54367f7143af9928f5286369e912c26cad5016d730c0ffb9797ac9e83831059d7f1d863f7dc84330eb02414611 - languageName: node - linkType: hard - -"eslint-utils@npm:^3.0.0": - version: 3.0.0 - resolution: "eslint-utils@npm:3.0.0" - dependencies: - eslint-visitor-keys: "npm:^2.0.0" - peerDependencies: - eslint: ">=5" - checksum: 45aa2b63667a8d9b474c98c28af908d0a592bed1a4568f3145cd49fb5d9510f545327ec95561625290313fe126e6d7bdfe3fdbdb6f432689fab6b9497d3bfb52 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^1.1.0, eslint-visitor-keys@npm:^1.3.0": - version: 1.3.0 - resolution: "eslint-visitor-keys@npm:1.3.0" - checksum: 10c91fdbbe36810dd4308e57f9a8bc7177188b2a70247e54e3af1fa05ebc66414ae6fd4ce3c6c6821591f43a556e9037bc6b071122e099b5f8b7d2f76df553e3 - languageName: node - linkType: hard - -"eslint-visitor-keys@npm:^2.0.0": - version: 2.1.0 - resolution: "eslint-visitor-keys@npm:2.1.0" - checksum: 9f0e3a2db751d84067d15977ac4b4472efd6b303e369e6ff241a99feac04da758f46d5add022c33d06b53596038dbae4b4aceb27c7e68b8dfc1055b35e495787 - languageName: node - linkType: hard - "eslint-visitor-keys@npm:^3.3.0, eslint-visitor-keys@npm:^3.4.1, eslint-visitor-keys@npm:^3.4.3": version: 3.4.3 resolution: "eslint-visitor-keys@npm:3.4.3" @@ -7754,65 +10394,63 @@ __metadata: languageName: node linkType: hard -"eslint@npm:^7.24.0": - version: 7.32.0 - resolution: "eslint@npm:7.32.0" +"eslint@npm:^8.52.0, eslint@npm:^8.56.0": + version: 8.56.0 + resolution: "eslint@npm:8.56.0" dependencies: - "@babel/code-frame": "npm:7.12.11" - "@eslint/eslintrc": "npm:^0.4.3" - "@humanwhocodes/config-array": "npm:^0.5.0" - ajv: "npm:^6.10.0" + "@eslint-community/eslint-utils": "npm:^4.2.0" + "@eslint-community/regexpp": "npm:^4.6.1" + "@eslint/eslintrc": "npm:^2.1.4" + "@eslint/js": "npm:8.56.0" + "@humanwhocodes/config-array": "npm:^0.11.13" + "@humanwhocodes/module-importer": "npm:^1.0.1" + "@nodelib/fs.walk": "npm:^1.2.8" + "@ungap/structured-clone": "npm:^1.2.0" + ajv: "npm:^6.12.4" chalk: "npm:^4.0.0" cross-spawn: "npm:^7.0.2" - debug: "npm:^4.0.1" + debug: "npm:^4.3.2" doctrine: "npm:^3.0.0" - enquirer: "npm:^2.3.5" escape-string-regexp: "npm:^4.0.0" - eslint-scope: "npm:^5.1.1" - eslint-utils: "npm:^2.1.0" - eslint-visitor-keys: "npm:^2.0.0" - espree: "npm:^7.3.1" - esquery: "npm:^1.4.0" + eslint-scope: "npm:^7.2.2" + eslint-visitor-keys: "npm:^3.4.3" + espree: "npm:^9.6.1" + esquery: "npm:^1.4.2" esutils: "npm:^2.0.2" fast-deep-equal: "npm:^3.1.3" file-entry-cache: "npm:^6.0.1" - functional-red-black-tree: "npm:^1.0.1" - glob-parent: "npm:^5.1.2" - globals: "npm:^13.6.0" - ignore: "npm:^4.0.6" - import-fresh: "npm:^3.0.0" + find-up: "npm:^5.0.0" + glob-parent: "npm:^6.0.2" + globals: "npm:^13.19.0" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.2.0" imurmurhash: "npm:^0.1.4" is-glob: "npm:^4.0.0" - js-yaml: "npm:^3.13.1" + is-path-inside: "npm:^3.0.3" + js-yaml: "npm:^4.1.0" json-stable-stringify-without-jsonify: "npm:^1.0.1" levn: "npm:^0.4.1" lodash.merge: "npm:^4.6.2" - minimatch: "npm:^3.0.4" + minimatch: "npm:^3.1.2" natural-compare: "npm:^1.4.0" - optionator: "npm:^0.9.1" - progress: "npm:^2.0.0" - regexpp: "npm:^3.1.0" - semver: "npm:^7.2.1" - strip-ansi: "npm:^6.0.0" - strip-json-comments: "npm:^3.1.0" - table: "npm:^6.0.9" + optionator: "npm:^0.9.3" + strip-ansi: "npm:^6.0.1" text-table: "npm:^0.2.0" - v8-compile-cache: "npm:^2.0.3" bin: eslint: bin/eslint.js - checksum: 84409f7767556179cb11529f1215f335c7dfccf90419df6147f949f14c347a960c7b569e80ed84011a0b6d10da1ef5046edbbb9b11c3e59aa6696d5217092e93 + checksum: 2be598f7da1339d045ad933ffd3d4742bee610515cd2b0d9a2b8b729395a01d4e913552fff555b559fccaefd89d7b37632825789d1b06470608737ae69ab43fb languageName: node linkType: hard -"eslint@npm:^8.52.0": - version: 8.54.0 - resolution: "eslint@npm:8.54.0" +"eslint@npm:^8.57.0": + version: 8.57.0 + resolution: "eslint@npm:8.57.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.2.0" "@eslint-community/regexpp": "npm:^4.6.1" - "@eslint/eslintrc": "npm:^2.1.3" - "@eslint/js": "npm:8.54.0" - "@humanwhocodes/config-array": "npm:^0.11.13" + "@eslint/eslintrc": "npm:^2.1.4" + "@eslint/js": "npm:8.57.0" + "@humanwhocodes/config-array": "npm:^0.11.14" "@humanwhocodes/module-importer": "npm:^1.0.1" "@nodelib/fs.walk": "npm:^1.2.8" "@ungap/structured-clone": "npm:^1.2.0" @@ -7848,18 +10486,19 @@ __metadata: text-table: "npm:^0.2.0" bin: eslint: bin/eslint.js - checksum: 4f205f832bdbd0218cde374b067791f4f76d7abe8de86b2dc849c273899051126d912ebf71531ee49b8eeaa22cad77febdc8f2876698dc2a76e84a8cb976af22 + checksum: 00bb96fd2471039a312435a6776fe1fd557c056755eaa2b96093ef3a8508c92c8775d5f754768be6b1dddd09fdd3379ddb231eeb9b6c579ee17ea7d68000a529 languageName: node linkType: hard -"espree@npm:^7.3.0, espree@npm:^7.3.1": - version: 7.3.1 - resolution: "espree@npm:7.3.1" +"esniff@npm:^2.0.1": + version: 2.0.1 + resolution: "esniff@npm:2.0.1" dependencies: - acorn: "npm:^7.4.0" - acorn-jsx: "npm:^5.3.1" - eslint-visitor-keys: "npm:^1.3.0" - checksum: f4e81b903f03eaf0e6925cea20571632da427deb6e14ca37e481f72c11f36d7bb4945fe8a2ff15ab22d078d3cd93ee65355fa94de9c27485c356481775f25d85 + d: "npm:^1.0.1" + es5-ext: "npm:^0.10.62" + event-emitter: "npm:^0.3.5" + type: "npm:^2.7.2" + checksum: 7efd8d44ac20e5db8cb0ca77eb65eca60628b2d0f3a1030bcb05e71cc40e6e2935c47b87dba3c733db12925aa5b897f8e0e7a567a2c274206f184da676ea2e65 languageName: node linkType: hard @@ -7894,7 +10533,7 @@ __metadata: languageName: node linkType: hard -"esquery@npm:^1.4.0, esquery@npm:^1.4.2": +"esquery@npm:^1.4.2": version: 1.5.0 resolution: "esquery@npm:1.5.0" dependencies: @@ -7919,14 +10558,7 @@ __metadata: languageName: node linkType: hard -"estraverse@npm:^4.1.1": - version: 4.3.0 - resolution: "estraverse@npm:4.3.0" - checksum: 9cb46463ef8a8a4905d3708a652d60122a0c20bb58dec7e0e12ab0e7235123d74214fc0141d743c381813e1b992767e2708194f6f6e0f9fd00c1b4e0887b8b6d - languageName: node - linkType: hard - -"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0, estraverse@npm:^5.3.0": version: 5.3.0 resolution: "estraverse@npm:5.3.0" checksum: 1ff9447b96263dec95d6d67431c5e0771eb9776427421260a3e2f0fdd5d6bd4f8e37a7338f5ad2880c9f143450c9b1e4fc2069060724570a49cf9cf0312bd107 @@ -8179,18 +10811,18 @@ __metadata: linkType: hard "ethereum-cryptography@npm:^2.0.0, ethereum-cryptography@npm:^2.1.2": - version: 2.1.2 - resolution: "ethereum-cryptography@npm:2.1.2" + version: 2.1.3 + resolution: "ethereum-cryptography@npm:2.1.3" dependencies: - "@noble/curves": "npm:1.1.0" - "@noble/hashes": "npm:1.3.1" - "@scure/bip32": "npm:1.3.1" - "@scure/bip39": "npm:1.2.1" - checksum: 784552709e3afd4ae9c606f3cf04ced49ab69f3864df58aca64f15317641470afd44573cbda821b9cf6781dac6dd3a95559fcc062299e23394094a3370387ec6 + "@noble/curves": "npm:1.3.0" + "@noble/hashes": "npm:1.3.3" + "@scure/bip32": "npm:1.3.3" + "@scure/bip39": "npm:1.2.2" + checksum: a2f25ad5ffa44b4364b1540a57969ee6f1dd820aa08a446f40f31203fef54a09442a6c099e70e7c1485922f6391c4c45b90f2c401e04d88ac9cc4611b05e606f languageName: node linkType: hard -"ethereum-waffle@npm:^3.2.0": +"ethereum-waffle@npm:^3.1.1, ethereum-waffle@npm:^3.2.0": version: 3.4.4 resolution: "ethereum-waffle@npm:3.4.4" dependencies: @@ -8543,7 +11175,7 @@ __metadata: languageName: node linkType: hard -"ethers@npm:^5.0.1, ethers@npm:^5.0.2, ethers@npm:^5.1.0, ethers@npm:^5.5.2, ethers@npm:^5.6.0, ethers@npm:^5.6.1, ethers@npm:^5.7.0, ethers@npm:^5.7.1, ethers@npm:^5.7.2": +"ethers@npm:^5.0.1, ethers@npm:^5.0.18, ethers@npm:^5.0.2, ethers@npm:^5.1.0, ethers@npm:^5.5.2, ethers@npm:^5.6.0, ethers@npm:^5.6.1, ethers@npm:^5.7.0, ethers@npm:^5.7.1, ethers@npm:^5.7.2": version: 5.7.2 resolution: "ethers@npm:5.7.2" dependencies: @@ -8601,6 +11233,16 @@ __metadata: languageName: node linkType: hard +"event-emitter@npm:^0.3.5": + version: 0.3.5 + resolution: "event-emitter@npm:0.3.5" + dependencies: + d: "npm:1" + es5-ext: "npm:~0.10.14" + checksum: 75082fa8ffb3929766d0f0a063bfd6046bd2a80bea2666ebaa0cfd6f4a9116be6647c15667bea77222afc12f5b4071b68d393cf39fdaa0e8e81eda006160aff0 + languageName: node + linkType: hard + "event-target-shim@npm:^5.0.0": version: 5.0.1 resolution: "event-target-shim@npm:5.0.1" @@ -8674,23 +11316,6 @@ __metadata: languageName: node linkType: hard -"execa@npm:^7.1.1": - version: 7.2.0 - resolution: "execa@npm:7.2.0" - dependencies: - cross-spawn: "npm:^7.0.3" - get-stream: "npm:^6.0.1" - human-signals: "npm:^4.3.0" - is-stream: "npm:^3.0.0" - merge-stream: "npm:^2.0.0" - npm-run-path: "npm:^5.1.0" - onetime: "npm:^6.0.0" - signal-exit: "npm:^3.0.7" - strip-final-newline: "npm:^3.0.0" - checksum: 098cd6a1bc26d509e5402c43f4971736450b84d058391820c6f237aeec6436963e006fd8423c9722f148c53da86aa50045929c7278b5522197dff802d10f9885 - languageName: node - linkType: hard - "expand-brackets@npm:^2.1.4": version: 2.1.4 resolution: "expand-brackets@npm:2.1.4" @@ -8825,7 +11450,14 @@ __metadata: languageName: node linkType: hard -"external-editor@npm:^3.0.3": +"extendable-error@npm:^0.1.5": + version: 0.1.7 + resolution: "extendable-error@npm:0.1.7" + checksum: c46648b7682448428f81b157cbfe480170fd96359c55db477a839ddeaa34905a18cba0b989bafe5e83f93c2491a3fcc7cc536063ea326ba9d72e9c6e2fe736a7 + languageName: node + linkType: hard + +"external-editor@npm:^3.0.3, external-editor@npm:^3.1.0": version: 3.1.0 resolution: "external-editor@npm:3.1.0" dependencies: @@ -8852,6 +11484,13 @@ __metadata: languageName: node linkType: hard +"extract-files@npm:^11.0.0": + version: 11.0.0 + resolution: "extract-files@npm:11.0.0" + checksum: 7ac1cd693d081099d7c29f2b36aad199f92c5ea234c2016eb37ba213dddaefe74d54566f0675de5917d35cf98670183c2c9a0d96094727eb2c6dae02be7fc308 + languageName: node + linkType: hard + "extsprintf@npm:1.3.0": version: 1.3.0 resolution: "extsprintf@npm:1.3.0" @@ -8882,6 +11521,13 @@ __metadata: languageName: node linkType: hard +"fast-decode-uri-component@npm:^1.0.1": + version: 1.0.1 + resolution: "fast-decode-uri-component@npm:1.0.1" + checksum: 039d50c2e99d64f999c3f2126c23fbf75a04a4117e218a149ca0b1d2aeb8c834b7b19d643b9d35d4eabce357189a6a94085f78cf48869e6e26cc59b036284bc3 + languageName: node + linkType: hard + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -8903,7 +11549,7 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.9, fast-glob@npm:^3.3.0": +"fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.9": version: 3.3.2 resolution: "fast-glob@npm:3.3.2" dependencies: @@ -8930,6 +11576,15 @@ __metadata: languageName: node linkType: hard +"fast-querystring@npm:^1.1.1": + version: 1.1.2 + resolution: "fast-querystring@npm:1.1.2" + dependencies: + fast-decode-uri-component: "npm:^1.0.1" + checksum: e8223273a9b199722f760f5a047a77ad049a14bd444b821502cb8218f5925e3a5fffb56b64389bca73ab2ac6f1aa7aebbe4e203e5f6e53ff5978de97c0fde4e3 + languageName: node + linkType: hard + "fast-redact@npm:^3.0.0": version: 3.3.0 resolution: "fast-redact@npm:3.3.0" @@ -8937,6 +11592,15 @@ __metadata: languageName: node linkType: hard +"fast-url-parser@npm:^1.1.3": + version: 1.1.3 + resolution: "fast-url-parser@npm:1.1.3" + dependencies: + punycode: "npm:^1.3.2" + checksum: d85c5c409cf0215417380f98a2d29c23a95004d93ff0d8bdf1af5f1a9d1fc608ac89ac6ffe863783d2c73efb3850dd35390feb1de3296f49877bfee0392eb5d3 + languageName: node + linkType: hard + "fastify-warning@npm:^0.2.0": version: 0.2.0 resolution: "fastify-warning@npm:0.2.0" @@ -8945,11 +11609,42 @@ __metadata: linkType: hard "fastq@npm:^1.6.0": - version: 1.15.0 - resolution: "fastq@npm:1.15.0" + version: 1.17.1 + resolution: "fastq@npm:1.17.1" dependencies: reusify: "npm:^1.0.4" - checksum: 5ce4f83afa5f88c9379e67906b4d31bc7694a30826d6cc8d0f0473c966929017fda65c2174b0ec89f064ede6ace6c67f8a4fe04cef42119b6a55b0d465554c24 + checksum: 1095f16cea45fb3beff558bb3afa74ca7a9250f5a670b65db7ed585f92b4b48381445cd328b3d87323da81e43232b5d5978a8201bde84e0cd514310f1ea6da34 + languageName: node + linkType: hard + +"fb-watchman@npm:^2.0.0": + version: 2.0.2 + resolution: "fb-watchman@npm:2.0.2" + dependencies: + bser: "npm:2.1.1" + checksum: feae89ac148adb8f6ae8ccd87632e62b13563e6fb114cacb5265c51f585b17e2e268084519fb2edd133872f1d47a18e6bfd7e5e08625c0d41b93149694187581 + languageName: node + linkType: hard + +"fbjs-css-vars@npm:^1.0.0": + version: 1.0.2 + resolution: "fbjs-css-vars@npm:1.0.2" + checksum: dfb64116b125a64abecca9e31477b5edb9a2332c5ffe74326fe36e0a72eef7fc8a49b86adf36c2c293078d79f4524f35e80f5e62546395f53fb7c9e69821f54f + languageName: node + linkType: hard + +"fbjs@npm:^3.0.0": + version: 3.0.5 + resolution: "fbjs@npm:3.0.5" + dependencies: + cross-fetch: "npm:^3.1.5" + fbjs-css-vars: "npm:^1.0.0" + loose-envify: "npm:^1.0.0" + object-assign: "npm:^4.1.0" + promise: "npm:^7.1.1" + setimmediate: "npm:^1.0.5" + ua-parser-js: "npm:^1.0.35" + checksum: 66d0a2fc9a774f9066e35ac2ac4bf1245931d27f3ac287c7d47e6aa1fc152b243c2109743eb8f65341e025621fb51a12038fadb9fd8fda2e3ddae04ebab06f91 languageName: node linkType: hard @@ -8969,6 +11664,26 @@ __metadata: languageName: node linkType: hard +"fets@npm:^0.1.1": + version: 0.1.5 + resolution: "fets@npm:0.1.5" + dependencies: + "@ardatan/fast-json-stringify": "npm:^0.0.6" + "@whatwg-node/cookie-store": "npm:^0.0.1" + "@whatwg-node/fetch": "npm:^0.8.2" + "@whatwg-node/server": "npm:^0.7.4" + ajv: "npm:^8.12.0" + ajv-formats: "npm:^2.1.1" + hotscript: "npm:^1.0.11" + json-schema-to-ts: "npm:^2.7.2" + openapi-types: "npm:^12.1.0" + tslib: "npm:^2.3.1" + zod: "npm:^3.21.4" + zod-to-json-schema: "npm:^3.20.5" + checksum: 52ebcac126c5c217ef70687e5390467f33e32ef24bd251e672625411405b15f7dc5eb3591a9c9932eacd90f2fa0715dc26392e24d114a62a12fedc49e344cac9 + languageName: node + linkType: hard + "figures@npm:^3.0.0": version: 3.2.0 resolution: "figures@npm:3.2.0" @@ -9077,7 +11792,7 @@ __metadata: languageName: node linkType: hard -"find-up@npm:^4.1.0": +"find-up@npm:^4.0.0, find-up@npm:^4.1.0": version: 4.1.0 resolution: "find-up@npm:4.1.0" dependencies: @@ -9087,6 +11802,16 @@ __metadata: languageName: node linkType: hard +"find-yarn-workspace-root2@npm:1.2.16": + version: 1.2.16 + resolution: "find-yarn-workspace-root2@npm:1.2.16" + dependencies: + micromatch: "npm:^4.0.2" + pkg-dir: "npm:^4.2.0" + checksum: d576067c7823de517d71831eafb5f6dc60554335c2d14445708f2698551b234f89c976a7f259d9355a44e417c49e7a93b369d0474579af02bbe2498f780c92d3 + languageName: node + linkType: hard + "find-yarn-workspace-root@npm:^1.2.1": version: 1.2.1 resolution: "find-yarn-workspace-root@npm:1.2.1" @@ -9127,9 +11852,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.2.9 - resolution: "flatted@npm:3.2.9" - checksum: 5c91c5a0a21bbc0b07b272231e5b4efe6b822bcb4ad317caf6bb06984be4042a9e9045026307da0fdb4583f1f545e317a67ef1231a59e71f7fced3cc429cfc53 + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 324166b125ee07d4ca9bcf3a5f98d915d5db4f39d711fba640a3178b959919aae1f7cfd8aabcfef5826ed8aa8a2aa14cc85b2d7d18ff638ddf4ae3df39573eaf languageName: node linkType: hard @@ -9140,6 +11865,15 @@ __metadata: languageName: node linkType: hard +"fmix@npm:^0.1.0": + version: 0.1.0 + resolution: "fmix@npm:0.1.0" + dependencies: + imul: "npm:^1.0.0" + checksum: af9e54eacc00b46e1c4a77229840e37252fff7634f81026591da9d24438ca15a1afa2786f579eb7865489ded21b76af7327d111b90b944e7409cd60f4d4f2ded + languageName: node + linkType: hard + "fn.name@npm:1.x.x": version: 1.1.0 resolution: "fn.name@npm:1.1.0" @@ -9147,13 +11881,13 @@ __metadata: languageName: node linkType: hard -"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.0": - version: 1.15.3 - resolution: "follow-redirects@npm:1.15.3" +"follow-redirects@npm:^1.12.1, follow-redirects@npm:^1.14.0, follow-redirects@npm:^1.15.4": + version: 1.15.5 + resolution: "follow-redirects@npm:1.15.5" peerDependenciesMeta: debug: optional: true - checksum: 915a2cf22e667bdf47b1a43cc6b7dce14d95039e9bbf9a24d0e739abfbdfa00077dd43c86d4a7a19efefcc7a99af144920a175eedc3888d268af5df67c272ee5 + checksum: 418d71688ceaf109dfd6f85f747a0c75de30afe43a294caa211def77f02ef19865b547dfb73fde82b751e1cc507c06c754120b848fe5a7400b0a669766df7615 languageName: node linkType: hard @@ -9173,6 +11907,13 @@ __metadata: languageName: node linkType: hard +"foreach@npm:^2.0.4": + version: 2.0.6 + resolution: "foreach@npm:2.0.6" + checksum: dc79f83997ac986dadbc95b4035ce8b86699fb654eb85446b0ad779fe69d567fc9894075e460243ca8bc20adb8fd178ad203aef66dc3c620ac78b18a4cb7059c + languageName: node + linkType: hard + "foreground-child@npm:^3.1.0": version: 3.1.1 resolution: "foreground-child@npm:3.1.1" @@ -9197,6 +11938,13 @@ __metadata: languageName: node linkType: hard +"form-data-encoder@npm:^2.1.2": + version: 2.1.4 + resolution: "form-data-encoder@npm:2.1.4" + checksum: 4c06ae2b79ad693a59938dc49ebd020ecb58e4584860a90a230f80a68b026483b022ba5e4143cff06ae5ac8fd446a0b500fabc87bbac3d1f62f2757f8dabcaf7 + languageName: node + linkType: hard + "form-data@npm:^2.2.0": version: 2.5.1 resolution: "form-data@npm:2.5.1" @@ -9291,17 +12039,6 @@ __metadata: languageName: node linkType: hard -"fs-extra@npm:^11.0.0": - version: 11.2.0 - resolution: "fs-extra@npm:11.2.0" - dependencies: - graceful-fs: "npm:^4.2.0" - jsonfile: "npm:^6.0.1" - universalify: "npm:^2.0.0" - checksum: d77a9a9efe60532d2e790e938c81a02c1b24904ef7a3efb3990b835514465ba720e99a6ea56fd5e2db53b4695319b644d76d5a0e9988a2beef80aa7b1da63398 - languageName: node - linkType: hard - "fs-extra@npm:^4.0.2, fs-extra@npm:^4.0.3": version: 4.0.3 resolution: "fs-extra@npm:4.0.3" @@ -9483,6 +12220,13 @@ __metadata: languageName: node linkType: hard +"gensync@npm:^1.0.0-beta.2": + version: 1.0.0-beta.2 + resolution: "gensync@npm:1.0.0-beta.2" + checksum: 782aba6cba65b1bb5af3b095d96249d20edbe8df32dbf4696fd49be2583faf676173bf4809386588828e4dd76a3354fcbeb577bab1c833ccd9fc4577f26103f8 + languageName: node + linkType: hard + "get-caller-file@npm:^1.0.1": version: 1.0.3 resolution: "get-caller-file@npm:1.0.3" @@ -9490,7 +12234,7 @@ __metadata: languageName: node linkType: hard -"get-caller-file@npm:^2.0.5": +"get-caller-file@npm:^2.0.1, get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" checksum: c6c7b60271931fa752aeb92f2b47e355eac1af3a2673f47c9589e8f8a41adc74d45551c1bc57b5e66a80609f10ffb72b6f575e4370d61cc3f7f3aaff01757cde @@ -9504,15 +12248,16 @@ __metadata: languageName: node linkType: hard -"get-intrinsic@npm:^1.0.2, get-intrinsic@npm:^1.1.1, get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.0, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2": - version: 1.2.2 - resolution: "get-intrinsic@npm:1.2.2" +"get-intrinsic@npm:^1.1.3, get-intrinsic@npm:^1.2.1, get-intrinsic@npm:^1.2.2, get-intrinsic@npm:^1.2.3, get-intrinsic@npm:^1.2.4": + version: 1.2.4 + resolution: "get-intrinsic@npm:1.2.4" dependencies: + es-errors: "npm:^1.3.0" function-bind: "npm:^1.1.2" has-proto: "npm:^1.0.1" has-symbols: "npm:^1.0.3" hasown: "npm:^2.0.0" - checksum: 4e7fb8adc6172bae7c4fe579569b4d5238b3667c07931cd46b4eee74bbe6ff6b91329bec311a638d8e60f5b51f44fe5445693c6be89ae88d4b5c49f7ff12db0b + checksum: 0a9b82c16696ed6da5e39b1267104475c47e3a9bdbe8b509dfe1710946e38a87be70d759f4bb3cda042d76a41ef47fe769660f3b7c0d1f68750299344ffb15b7 languageName: node linkType: hard @@ -9562,13 +12307,14 @@ __metadata: languageName: node linkType: hard -"get-symbol-description@npm:^1.0.0": - version: 1.0.0 - resolution: "get-symbol-description@npm:1.0.0" +"get-symbol-description@npm:^1.0.2": + version: 1.0.2 + resolution: "get-symbol-description@npm:1.0.2" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.1.1" - checksum: 23bc3b44c221cdf7669a88230c62f4b9e30393b61eb21ba4400cb3e346801bd8f95fe4330ee78dbae37aecd874646d53e3e76a17a654d0c84c77f6690526d6bb + call-bind: "npm:^1.0.5" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.4" + checksum: 867be6d63f5e0eb026cb3b0ef695ec9ecf9310febb041072d2e142f260bd91ced9eeb426b3af98791d1064e324e653424afa6fd1af17dee373bea48ae03162bc languageName: node linkType: hard @@ -9647,7 +12393,20 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10": +"glob@npm:8.1.0, glob@npm:^8.0.3": + version: 8.1.0 + resolution: "glob@npm:8.1.0" + dependencies: + fs.realpath: "npm:^1.0.0" + inflight: "npm:^1.0.4" + inherits: "npm:2" + minimatch: "npm:^5.0.1" + once: "npm:^1.3.0" + checksum: cb0b5cab17a59c57299376abe5646c7070f8acb89df5595b492dba3bfb43d301a46c01e5695f01154e6553168207cb60d4eaf07d3be4bc3eb9b0457c5c561d0f + languageName: node + linkType: hard + +"glob@npm:^10.2.2, glob@npm:^10.3.10, glob@npm:^10.3.7": version: 10.3.10 resolution: "glob@npm:10.3.10" dependencies: @@ -9675,7 +12434,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^7.0.0, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.6, glob@npm:~7.2.3": +"glob@npm:^7.0.0, glob@npm:^7.1.1, glob@npm:^7.1.2, glob@npm:^7.1.3, glob@npm:^7.1.6, glob@npm:~7.2.3": version: 7.2.3 resolution: "glob@npm:7.2.3" dependencies: @@ -9689,19 +12448,6 @@ __metadata: languageName: node linkType: hard -"glob@npm:^8.0.3": - version: 8.1.0 - resolution: "glob@npm:8.1.0" - dependencies: - fs.realpath: "npm:^1.0.0" - inflight: "npm:^1.0.4" - inherits: "npm:2" - minimatch: "npm:^5.0.1" - once: "npm:^1.3.0" - checksum: cb0b5cab17a59c57299376abe5646c7070f8acb89df5595b492dba3bfb43d301a46c01e5695f01154e6553168207cb60d4eaf07d3be4bc3eb9b0457c5c561d0f - languageName: node - linkType: hard - "global-dirs@npm:^0.1.1": version: 0.1.1 resolution: "global-dirs@npm:0.1.1" @@ -9741,12 +12487,19 @@ __metadata: languageName: node linkType: hard -"globals@npm:^13.19.0, globals@npm:^13.6.0, globals@npm:^13.9.0": - version: 13.23.0 - resolution: "globals@npm:13.23.0" +"globals@npm:^11.1.0": + version: 11.12.0 + resolution: "globals@npm:11.12.0" + checksum: 758f9f258e7b19226bd8d4af5d3b0dcf7038780fb23d82e6f98932c44e239f884847f1766e8fa9cc5635ccb3204f7fa7314d4408dd4002a5e8ea827b4018f0a1 + languageName: node + linkType: hard + +"globals@npm:^13.19.0": + version: 13.24.0 + resolution: "globals@npm:13.24.0" dependencies: type-fest: "npm:^0.20.2" - checksum: fc05e184b3be59bffa2580f28551a12a758c3a18df4be91444202982c76f13f52821ad54ffaf7d3f2a4d2498fdf54aeaca8d4540fd9e860a9edb09d34ef4c507 + checksum: d3c11aeea898eb83d5ec7a99508600fbe8f83d2cf00cbb77f873dbf2bcb39428eff1b538e4915c993d8a3b3473fa71eeebfe22c9bb3a3003d1e26b1f2c8a42cd languageName: node linkType: hard @@ -9782,7 +12535,7 @@ __metadata: languageName: node linkType: hard -"globby@npm:^11.0.3, globby@npm:^11.1.0": +"globby@npm:^11.0.0, globby@npm:^11.0.3, globby@npm:^11.1.0": version: 11.1.0 resolution: "globby@npm:11.1.0" dependencies: @@ -9864,13 +12617,46 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.1.9, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": +"got@npm:^12.1.0": + version: 12.6.1 + resolution: "got@npm:12.6.1" + dependencies: + "@sindresorhus/is": "npm:^5.2.0" + "@szmarczak/http-timer": "npm:^5.0.1" + cacheable-lookup: "npm:^7.0.0" + cacheable-request: "npm:^10.2.8" + decompress-response: "npm:^6.0.0" + form-data-encoder: "npm:^2.1.2" + get-stream: "npm:^6.0.1" + http2-wrapper: "npm:^2.1.10" + lowercase-keys: "npm:^3.0.0" + p-cancelable: "npm:^3.0.0" + responselike: "npm:^3.0.0" + checksum: 2fe97fcbd7a9ffc7c2d0ecf59aca0a0562e73a7749cadada9770eeb18efbdca3086262625fb65590594edc220a1eca58fab0d26b0c93c2f9a008234da71ca66b + languageName: node + linkType: hard + +"graceful-fs@npm:4.2.10": + version: 4.2.10 + resolution: "graceful-fs@npm:4.2.10" + checksum: 4223a833e38e1d0d2aea630c2433cfb94ddc07dfc11d511dbd6be1d16688c5be848acc31f9a5d0d0ddbfb56d2ee5a6ae0278aceeb0ca6a13f27e06b9956fb952 + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.11, graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.1.9, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 languageName: node linkType: hard +"grapheme-splitter@npm:^1.0.4": + version: 1.0.4 + resolution: "grapheme-splitter@npm:1.0.4" + checksum: 108415fb07ac913f17040dc336607772fcea68c7f495ef91887edddb0b0f5ff7bc1d1ab181b125ecb2f0505669ef12c9a178a3bbd2dd8e042d8c5f1d7c90331a + languageName: node + linkType: hard + "graphemer@npm:^1.4.0": version: 1.4.0 resolution: "graphemer@npm:1.4.0" @@ -9878,7 +12664,16 @@ __metadata: languageName: node linkType: hard -"graphql-tag@npm:2.12.6, graphql-tag@npm:^2.12.4": +"graphql-import-node@npm:^0.0.5": + version: 0.0.5 + resolution: "graphql-import-node@npm:0.0.5" + peerDependencies: + graphql: "*" + checksum: 97de408098985f9e5c5d3f2a898c700ea8222c578dc898289bbfea0066be73eb88cc58b1e3a8ae1c71a81651541d8da16bbddfb7a352afcc88edf026ad1fa13c + languageName: node + linkType: hard + +"graphql-tag@npm:2.12.6, graphql-tag@npm:^2.11.0, graphql-tag@npm:^2.12.4": version: 2.12.6 resolution: "graphql-tag@npm:2.12.6" dependencies: @@ -9889,6 +12684,46 @@ __metadata: languageName: node linkType: hard +"graphql-ws@npm:5.12.1": + version: 5.12.1 + resolution: "graphql-ws@npm:5.12.1" + peerDependencies: + graphql: ">=0.11 <=16" + checksum: 17338de4783b76e01a41e73a740beb72f9bde46750867463e394679cecc557f2af4ba59af8196e14aed1711a9b7ce6cff0149abc4ff27ca92497b988d6ebbac3 + languageName: node + linkType: hard + +"graphql-ws@npm:^5.12.1": + version: 5.15.0 + resolution: "graphql-ws@npm:5.15.0" + peerDependencies: + graphql: ">=0.11 <=16" + checksum: 4fcd93ed75261681b1def8cd96d1db0fc650586b145325b3fc134ab9c27ed48fbedad3e8261e3f3df65758a332d0420b8c60e13abb1ee8329ef624e312b61ccc + languageName: node + linkType: hard + +"graphql-yoga@npm:^3.9.1": + version: 3.9.1 + resolution: "graphql-yoga@npm:3.9.1" + dependencies: + "@envelop/core": "npm:^3.0.4" + "@envelop/validation-cache": "npm:^5.1.2" + "@graphql-tools/executor": "npm:^0.0.18" + "@graphql-tools/schema": "npm:^9.0.18" + "@graphql-tools/utils": "npm:^9.2.1" + "@graphql-yoga/logger": "npm:^0.0.1" + "@graphql-yoga/subscription": "npm:^3.1.0" + "@whatwg-node/fetch": "npm:^0.8.4" + "@whatwg-node/server": "npm:^0.7.3" + dset: "npm:^3.1.1" + lru-cache: "npm:^7.14.1" + tslib: "npm:^2.3.1" + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + checksum: aa01d62b9aa29c89eadaa178bb255a1aa756773e1e8da3fe32435fc157cdb313840e4db858ed0ec7ca209a113c23590f42ebb05c2e912f90353fba3a9b737212 + languageName: node + linkType: hard + "graphql@npm:16.3.0": version: 16.3.0 resolution: "graphql@npm:16.3.0" @@ -9903,6 +12738,13 @@ __metadata: languageName: node linkType: hard +"graphql@npm:^16.5.0": + version: 16.8.1 + resolution: "graphql@npm:16.8.1" + checksum: 129c318156b466f440914de80dbf7bc67d17f776f2a088a40cb0da611d19a97c224b1c6d2b13cbcbc6e5776e45ed7468b8432f9c3536724e079b44f1a3d57a8a + languageName: node + linkType: hard + "handlebars@npm:^4.0.1": version: 4.7.8 resolution: "handlebars@npm:4.7.8" @@ -9945,7 +12787,7 @@ __metadata: languageName: node linkType: hard -"hardhat-abi-exporter@npm:^2.2.0": +"hardhat-abi-exporter@npm:^2.0.1, hardhat-abi-exporter@npm:^2.2.0": version: 2.10.1 resolution: "hardhat-abi-exporter@npm:2.10.1" dependencies: @@ -9957,7 +12799,7 @@ __metadata: languageName: node linkType: hard -"hardhat-contract-sizer@npm:^2.0.3": +"hardhat-contract-sizer@npm:^2.0.1, hardhat-contract-sizer@npm:^2.0.3": version: 2.10.0 resolution: "hardhat-contract-sizer@npm:2.10.0" dependencies: @@ -9970,16 +12812,47 @@ __metadata: languageName: node linkType: hard -"hardhat-gas-reporter@npm:^1.0.4": - version: 1.0.9 - resolution: "hardhat-gas-reporter@npm:1.0.9" +"hardhat-deploy@npm:^0.7.0-beta.9": + version: 0.7.11 + resolution: "hardhat-deploy@npm:0.7.11" + dependencies: + "@ethersproject/abi": "npm:^5.0.0" + "@ethersproject/abstract-signer": "npm:^5.0.0" + "@ethersproject/address": "npm:^5.0.0" + "@ethersproject/bignumber": "npm:^5.0.0" + "@ethersproject/bytes": "npm:^5.0.0" + "@ethersproject/contracts": "npm:^5.0.0" + "@ethersproject/providers": "npm:^5.0.0" + "@ethersproject/solidity": "npm:^5.0.0" + "@ethersproject/transactions": "npm:^5.0.0" + "@ethersproject/wallet": "npm:^5.0.0" + "@types/qs": "npm:^6.9.4" + axios: "npm:^0.21.1" + chalk: "npm:^4.1.0" + chokidar: "npm:^3.4.0" + debug: "npm:^4.1.1" + form-data: "npm:^3.0.0" + fs-extra: "npm:^9.0.0" + match-all: "npm:^1.2.6" + murmur-128: "npm:^0.2.1" + qs: "npm:^6.9.4" + peerDependencies: + "@ethersproject/hardware-wallets": ^5.0.14 + hardhat: ^2.0.0 + checksum: 4a37daaf8866e51702db403b277b1d5fb848dab477de497ff8bd91c83da732a08501a5fe4a4398b9f2d0aff6bc66f32c98a61f15a15ed9e008ce99e71013eec9 + languageName: node + linkType: hard + +"hardhat-gas-reporter@npm:^1.0.1, hardhat-gas-reporter@npm:^1.0.4": + version: 1.0.10 + resolution: "hardhat-gas-reporter@npm:1.0.10" dependencies: array-uniq: "npm:1.0.3" eth-gas-reporter: "npm:^0.2.25" sha1: "npm:^1.1.1" peerDependencies: hardhat: ^2.0.2 - checksum: 2e3213dd821729a0ac63fba608125ad60d99fa1998b007fa0fb7a56f65dacbf786ece42ef2c902d7ca7660e1f6a7682a16a23a43f2d9277152f2665ae346bc8f + checksum: 3711ea331bcbbff4d37057cb3de47a9127011e3ee128c2254a68f3b7f12ab2133965cbcfa3a7ce1bba8461f3b1bda1b175c4814a048c8b06b3ad450001d119d8 languageName: node linkType: hard @@ -10039,22 +12912,23 @@ __metadata: languageName: node linkType: hard -"hardhat@npm:^2.6.4": - version: 2.19.1 - resolution: "hardhat@npm:2.19.1" +"hardhat@npm:^2.6.1, hardhat@npm:^2.6.4": + version: 2.20.1 + resolution: "hardhat@npm:2.20.1" dependencies: "@ethersproject/abi": "npm:^5.1.2" "@metamask/eth-sig-util": "npm:^4.0.0" - "@nomicfoundation/ethereumjs-block": "npm:5.0.2" - "@nomicfoundation/ethereumjs-blockchain": "npm:7.0.2" - "@nomicfoundation/ethereumjs-common": "npm:4.0.2" - "@nomicfoundation/ethereumjs-evm": "npm:2.0.2" - "@nomicfoundation/ethereumjs-rlp": "npm:5.0.2" - "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.2" - "@nomicfoundation/ethereumjs-trie": "npm:6.0.2" - "@nomicfoundation/ethereumjs-tx": "npm:5.0.2" - "@nomicfoundation/ethereumjs-util": "npm:9.0.2" - "@nomicfoundation/ethereumjs-vm": "npm:7.0.2" + "@nomicfoundation/ethereumjs-block": "npm:5.0.4" + "@nomicfoundation/ethereumjs-blockchain": "npm:7.0.4" + "@nomicfoundation/ethereumjs-common": "npm:4.0.4" + "@nomicfoundation/ethereumjs-evm": "npm:2.0.4" + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + "@nomicfoundation/ethereumjs-statemanager": "npm:2.0.4" + "@nomicfoundation/ethereumjs-trie": "npm:6.0.4" + "@nomicfoundation/ethereumjs-tx": "npm:5.0.4" + "@nomicfoundation/ethereumjs-util": "npm:9.0.4" + "@nomicfoundation/ethereumjs-verkle": "npm:0.0.2" + "@nomicfoundation/ethereumjs-vm": "npm:7.0.4" "@nomicfoundation/solidity-analyzer": "npm:^0.1.0" "@sentry/node": "npm:^5.18.1" "@types/bn.js": "npm:^5.1.0" @@ -10062,6 +12936,7 @@ __metadata: adm-zip: "npm:^0.4.16" aggregate-error: "npm:^3.0.0" ansi-escapes: "npm:^4.3.0" + boxen: "npm:^5.1.2" chalk: "npm:^2.4.2" chokidar: "npm:^3.4.0" ci-info: "npm:^2.0.0" @@ -10101,7 +12976,7 @@ __metadata: optional: true bin: hardhat: internal/cli/bootstrap.js - checksum: 613c7bd5a31a59cd641e4d883c0d05dfcd424af1018b0eaeb811f8ed470410e270a39f5cb5b00ce272d85430176c645a9d894f1af8930c0906a1fe978573229d + checksum: e27f1fc6b016d7ceb62795ff47384a02ad61722cdd2ab55c91d7ff2ce31973a1ea5e462431c7033ca53e66e4722c3597664b0ebaac70104622d227e94b4fb3e0 languageName: node linkType: hard @@ -10210,19 +13085,19 @@ __metadata: languageName: node linkType: hard -"has-property-descriptors@npm:^1.0.0": - version: 1.0.1 - resolution: "has-property-descriptors@npm:1.0.1" +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1, has-property-descriptors@npm:^1.0.2": + version: 1.0.2 + resolution: "has-property-descriptors@npm:1.0.2" dependencies: - get-intrinsic: "npm:^1.2.2" - checksum: d62ba94b40150b00d621bc64a6aedb5bf0ee495308b4b7ed6bac856043db3cdfb1db553ae81cec91c9d2bd82057ff0e94145e7fa25d5aa5985ed32e0921927f6 + es-define-property: "npm:^1.0.0" + checksum: 253c1f59e80bb476cf0dde8ff5284505d90c3bdb762983c3514d36414290475fe3fd6f574929d84de2a8eec00d35cf07cb6776205ff32efd7c50719125f00236 languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: c8a8fe411f810b23a564bd5546a8f3f0fff6f1b692740eb7a2fdc9df716ef870040806891e2f23ff4653f1083e3895bf12088703dd1a0eac3d9202d3a4768cd0 +"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: 35a6989f81e9f8022c2f4027f8b48a552de714938765d019dbea6bb547bd49ce5010a3c7c32ec6ddac6e48fc546166a3583b128f5a7add8b058a6d8b4afec205 languageName: node linkType: hard @@ -10233,12 +13108,12 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0": - version: 1.0.0 - resolution: "has-tostringtag@npm:1.0.0" +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.1, has-tostringtag@npm:^1.0.2": + version: 1.0.2 + resolution: "has-tostringtag@npm:1.0.2" dependencies: - has-symbols: "npm:^1.0.2" - checksum: 1cdba76b7d13f65198a92b8ca1560ba40edfa09e85d182bf436d928f3588a9ebd260451d569f0ed1b849c4bf54f49c862aa0d0a77f9552b1855bb6deb526c011 + has-symbols: "npm:^1.0.3" + checksum: a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c languageName: node linkType: hard @@ -10299,6 +13174,13 @@ __metadata: languageName: node linkType: hard +"hash-it@npm:^6.0.0": + version: 6.0.0 + resolution: "hash-it@npm:6.0.0" + checksum: edac58ed7b7a9e8e39e9991e89c97b5ce8235f340af4018037b4f3fb873a1e631505411543f41659888392a84b3c95b05dfc751355924b8216b8a2291775ce50 + languageName: node + linkType: hard + "hash.js@npm:1.1.3": version: 1.1.3 resolution: "hash.js@npm:1.1.3" @@ -10319,12 +13201,12 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0": - version: 2.0.0 - resolution: "hasown@npm:2.0.0" +"hasown@npm:^2.0.0, hasown@npm:^2.0.1": + version: 2.0.1 + resolution: "hasown@npm:2.0.1" dependencies: function-bind: "npm:^1.1.2" - checksum: 5d415b114f410661208c95e7ab4879f1cc2765b8daceff4dc8718317d1cb7b9ffa7c5d1eafd9a4389c9aab7445d6ea88e05f3096cb1e529618b55304956b87fc + checksum: 9e27e70e8e4204f4124c8f99950d1ba2b1f5174864fd39ff26da190f9ea6488c1b3927dcc64981c26d1f637a971783c9489d62c829d393ea509e6f1ba20370bb languageName: node linkType: hard @@ -10337,6 +13219,16 @@ __metadata: languageName: node linkType: hard +"header-case@npm:^2.0.4": + version: 2.0.4 + resolution: "header-case@npm:2.0.4" + dependencies: + capital-case: "npm:^1.0.4" + tslib: "npm:^2.0.3" + checksum: c9f295d9d8e38fa50679281fd70d80726962256e888a76c8e72e526453da7a1832dcb427caa716c1ad5d79841d4537301b90156fa30298fefd3d68f4ea2181bb + languageName: node + linkType: hard + "heap@npm:0.2.6": version: 0.2.6 resolution: "heap@npm:0.2.6" @@ -10395,6 +13287,13 @@ __metadata: languageName: node linkType: hard +"hotscript@npm:^1.0.11": + version: 1.0.13 + resolution: "hotscript@npm:1.0.13" + checksum: 423ea2aa437befeeffc32ea5a364b0d833f442fecdd7531c6fe8dc3df092c58d31145f757ad505ec7629ce4bb0eb8ff58889c8a58fe36312f975ff682f5cd422 + languageName: node + linkType: hard + "http-basic@npm:^8.1.1": version: 8.1.3 resolution: "http-basic@npm:8.1.3" @@ -10448,12 +13347,12 @@ __metadata: linkType: hard "http-proxy-agent@npm:^7.0.0": - version: 7.0.0 - resolution: "http-proxy-agent@npm:7.0.0" + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" dependencies: agent-base: "npm:^7.1.0" debug: "npm:^4.3.4" - checksum: a11574ff39436cee3c7bc67f259444097b09474605846ddd8edf0bf4ad8644be8533db1aa463426e376865047d05dc22755e638632819317c0c2f1b2196657c8 + checksum: 4207b06a4580fb85dd6dff521f0abf6db517489e70863dca1a0291daa7f2d3d2d6015a57bd702af068ea5cf9f1f6ff72314f5f5b4228d299c0904135d2aef921 languageName: node linkType: hard @@ -10508,12 +13407,19 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.2 - resolution: "https-proxy-agent@npm:7.0.2" + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" dependencies: agent-base: "npm:^7.0.2" debug: "npm:4" - checksum: 7735eb90073db087e7e79312e3d97c8c04baf7ea7ca7b013382b6a45abbaa61b281041a98f4e13c8c80d88f843785bcc84ba189165b4b4087b1e3496ba656d77 + checksum: bc4f7c38da32a5fc622450b6cb49a24ff596f9bd48dcedb52d2da3fa1c1a80e100fb506bd59b326c012f21c863c69b275c23de1a01d0b84db396822fdf25e52b + languageName: node + linkType: hard + +"human-id@npm:^1.0.2": + version: 1.0.2 + resolution: "human-id@npm:1.0.2" + checksum: e4c3be49b3927ff8ac54ae4a95ed77ad94fd793b57be51aff39aa81931c6efe56303ce1ec76a70c74f85748644207c89ccfa63d828def1313eff7526a14c3b3b languageName: node linkType: hard @@ -10531,13 +13437,6 @@ __metadata: languageName: node linkType: hard -"human-signals@npm:^4.3.0": - version: 4.3.1 - resolution: "human-signals@npm:4.3.1" - checksum: 40498b33fe139f5cc4ef5d2f95eb1803d6318ac1b1c63eaf14eeed5484d26332c828de4a5a05676b6c83d7b9e57727c59addb4b1dea19cb8d71e83689e5b336c - languageName: node - linkType: hard - "husky@npm:^8.0.3": version: 8.0.3 resolution: "husky@npm:8.0.3" @@ -10581,17 +13480,10 @@ __metadata: languageName: node linkType: hard -"ignore@npm:^4.0.6": - version: 4.0.6 - resolution: "ignore@npm:4.0.6" - checksum: 836ee7dc7fd9436096e2dba429359dbb9fa0e33d309e2b2d81692f375f6ca82024fc00567f798613d50c6b989e9cd2ad2b065acf116325cde177f02c86b7d4e0 - languageName: node - linkType: hard - -"ignore@npm:^5.1.1, ignore@npm:^5.1.8, ignore@npm:^5.2.0, ignore@npm:^5.2.4": - version: 5.3.0 - resolution: "ignore@npm:5.3.0" - checksum: dc06bea5c23aae65d0725a957a0638b57e235ae4568dda51ca142053ed2c352de7e3bc93a69b2b32ac31966a1952e9a93c5ef2e2ab7c6b06aef9808f6b55b571 +"ignore@npm:^5.1.1, ignore@npm:^5.2.0, ignore@npm:^5.2.4": + version: 5.3.1 + resolution: "ignore@npm:5.3.1" + checksum: 703f7f45ffb2a27fb2c5a8db0c32e7dee66b33a225d28e8db4e1be6474795f606686a6e3bcc50e1aa12f2042db4c9d4a7d60af3250511de74620fbed052ea4cd languageName: node linkType: hard @@ -10602,6 +13494,13 @@ __metadata: languageName: node linkType: hard +"immediate@npm:~3.0.5": + version: 3.0.6 + resolution: "immediate@npm:3.0.6" + checksum: f8ba7ede69bee9260241ad078d2d535848745ff5f6995c7c7cb41cfdc9ccc213f66e10fa5afb881f90298b24a3f7344b637b592beb4f54e582770cdce3f1f039 + languageName: node + linkType: hard + "immediate@npm:~3.2.3": version: 3.2.3 resolution: "immediate@npm:3.2.3" @@ -10610,9 +13509,16 @@ __metadata: linkType: hard "immutable@npm:^4.0.0-rc.12": - version: 4.3.4 - resolution: "immutable@npm:4.3.4" - checksum: c15b9f0fa7b3c9315725cb00704fddad59f0e668a7379c39b9a528a8386140ee9effb015ae51a5b423e05c59d15fc0b38c970db6964ad6b3e05d0761db68441f + version: 4.3.5 + resolution: "immutable@npm:4.3.5" + checksum: 63d2d7908241a955d18c7822fd2215b6e89ff5a1a33cc72cd475b013cbbdef7a705aa5170a51ce9f84a57f62fdddfaa34e7b5a14b33d8a43c65cc6a881d6e894 + languageName: node + linkType: hard + +"immutable@npm:~3.7.6": + version: 3.7.6 + resolution: "immutable@npm:3.7.6" + checksum: efe2bbb2620aa897afbb79545b9eda4dd3dc072e05ae7004895a7efb43187e4265612a88f8723f391eb1c87c46c52fd11e2d1968e42404450c63e49558d7ca4e languageName: node linkType: hard @@ -10626,6 +13532,20 @@ __metadata: languageName: node linkType: hard +"import-from@npm:4.0.0": + version: 4.0.0 + resolution: "import-from@npm:4.0.0" + checksum: 7fd98650d555e418c18341fef49ae11afc833f5ae70b7043e99684187cba6ac6b52e4118a491bd9f856045495bef5bdda7321095e65bcb2ef70ce2adf9f0d8d1 + languageName: node + linkType: hard + +"imul@npm:^1.0.0": + version: 1.0.1 + resolution: "imul@npm:1.0.1" + checksum: d564c45a5017f01f965509ef409fad8175749bc96a52a95e1a09f05378d135fb37051cea7194d0eeca5147541d8e80d68853f5f681eef05f9f14f1d551edae2f + languageName: node + linkType: hard + "imurmurhash@npm:^0.1.4": version: 0.1.4 resolution: "imurmurhash@npm:0.1.4" @@ -10664,13 +13584,34 @@ __metadata: languageName: node linkType: hard -"ini@npm:^1.3.4, ini@npm:^1.3.5": +"ini@npm:^1.3.4, ini@npm:^1.3.5, ini@npm:~1.3.0": version: 1.3.8 resolution: "ini@npm:1.3.8" checksum: ec93838d2328b619532e4f1ff05df7909760b6f66d9c9e2ded11e5c1897d6f2f9980c54dd638f88654b00919ce31e827040631eab0a3969e4d1abefa0719516a languageName: node linkType: hard +"inquirer@npm:8.0.0": + version: 8.0.0 + resolution: "inquirer@npm:8.0.0" + dependencies: + ansi-escapes: "npm:^4.2.1" + chalk: "npm:^4.1.0" + cli-cursor: "npm:^3.1.0" + cli-width: "npm:^3.0.0" + external-editor: "npm:^3.0.3" + figures: "npm:^3.0.0" + lodash: "npm:^4.17.21" + mute-stream: "npm:0.0.8" + run-async: "npm:^2.4.0" + rxjs: "npm:^6.6.6" + string-width: "npm:^4.1.0" + strip-ansi: "npm:^6.0.0" + through: "npm:^2.3.6" + checksum: b3fc16ed90bfc073fd5af64e150de67188ab321998a8f65eca682d127287c919e22c701a3c4546e2e224a1c2ac490cf3c1788a92d29505813d2ebe3b9d6a03be + languageName: node + linkType: hard + "inquirer@npm:^8.0.0": version: 8.2.6 resolution: "inquirer@npm:8.2.6" @@ -10694,14 +13635,14 @@ __metadata: languageName: node linkType: hard -"internal-slot@npm:^1.0.5": - version: 1.0.6 - resolution: "internal-slot@npm:1.0.6" +"internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" dependencies: - get-intrinsic: "npm:^1.2.2" + es-errors: "npm:^1.3.0" hasown: "npm:^2.0.0" side-channel: "npm:^1.0.4" - checksum: aa37cafc8ffbf513a340de58f40d5017b4949d99722d7e4f0e24b182455bdd258000d4bb1d7b4adcf9f8979b97049b99fe9defa9db8e18a78071d2637ac143fb + checksum: f8b294a4e6ea3855fc59551bbf35f2b832cf01fd5e6e2a97f5c201a071cc09b49048f856e484b67a6c721da5e55736c5b6ddafaf19e2dbeb4a3ff1821680de6c languageName: node linkType: hard @@ -10712,7 +13653,7 @@ __metadata: languageName: node linkType: hard -"invariant@npm:^2.2.2": +"invariant@npm:^2.2.2, invariant@npm:^2.2.4": version: 2.2.4 resolution: "invariant@npm:2.2.4" dependencies: @@ -10737,6 +13678,16 @@ __metadata: languageName: node linkType: hard +"ip-address@npm:^9.0.5": + version: 9.0.5 + resolution: "ip-address@npm:9.0.5" + dependencies: + jsbn: "npm:1.1.0" + sprintf-js: "npm:^1.1.3" + checksum: 331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc + languageName: node + linkType: hard + "ip-regex@npm:^4.0.0": version: 4.3.0 resolution: "ip-regex@npm:4.3.0" @@ -10744,13 +13695,6 @@ __metadata: languageName: node linkType: hard -"ip@npm:^2.0.0": - version: 2.0.0 - resolution: "ip@npm:2.0.0" - checksum: 8d186cc5585f57372847ae29b6eba258c68862055e18a75cc4933327232cb5c107f89800ce29715d542eef2c254fbb68b382e780a7414f9ee7caf60b7a473958 - languageName: node - linkType: hard - "ipaddr.js@npm:1.9.1": version: 1.9.1 resolution: "ipaddr.js@npm:1.9.1" @@ -10877,10 +13821,20 @@ __metadata: version: 6.0.0 resolution: "ipld-raw@npm:6.0.0" dependencies: - cids: "npm:^1.0.0" - multicodec: "npm:^2.0.0" - multihashing-async: "npm:^2.0.0" - checksum: af91bc865f6fba11bf4ed145a29ed0156f4acd71e39fb25cdb0c5fcb761d47ee68e39ff0fb254f939f125fc2dc9eee22dc943e95c44d154b674d4fb5295ecfce + cids: "npm:^1.0.0" + multicodec: "npm:^2.0.0" + multihashing-async: "npm:^2.0.0" + checksum: af91bc865f6fba11bf4ed145a29ed0156f4acd71e39fb25cdb0c5fcb761d47ee68e39ff0fb254f939f125fc2dc9eee22dc943e95c44d154b674d4fb5295ecfce + languageName: node + linkType: hard + +"is-absolute@npm:^1.0.0": + version: 1.0.0 + resolution: "is-absolute@npm:1.0.0" + dependencies: + is-relative: "npm:^1.0.0" + is-windows: "npm:^1.0.1" + checksum: 422302ce879d4f3ca6848499b6f3ddcc8fd2dc9f3e9cad3f6bcedff58cdfbbbd7f4c28600fffa7c59a858f1b15c27fb6cfe1d5275e58a36d2bf098a44ef5abc4 languageName: node linkType: hard @@ -10903,14 +13857,13 @@ __metadata: languageName: node linkType: hard -"is-array-buffer@npm:^3.0.1, is-array-buffer@npm:^3.0.2": - version: 3.0.2 - resolution: "is-array-buffer@npm:3.0.2" +"is-array-buffer@npm:^3.0.4": + version: 3.0.4 + resolution: "is-array-buffer@npm:3.0.4" dependencies: call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.0" - is-typed-array: "npm:^1.1.10" - checksum: 40ed13a5f5746ac3ae2f2e463687d9b5a3f5fd0086f970fb4898f0253c2a5ec2e3caea2d664dd8f54761b1c1948609702416921a22faebe160c7640a9217c80e + get-intrinsic: "npm:^1.2.1" + checksum: 42a49d006cc6130bc5424eae113e948c146f31f9d24460fc0958f855d9d810e6fd2e4519bf19aab75179af9c298ea6092459d8cafdec523cd19e529b26eab860 languageName: node linkType: hard @@ -11051,15 +14004,6 @@ __metadata: languageName: node linkType: hard -"is-docker@npm:^3.0.0": - version: 3.0.0 - resolution: "is-docker@npm:3.0.0" - bin: - is-docker: cli.js - checksum: d2c4f8e6d3e34df75a5defd44991b6068afad4835bb783b902fa12d13ebdb8f41b2a199dcb0b5ed2cb78bfee9e4c0bbdb69c2d9646f4106464674d3e697a5856 - languageName: node - linkType: hard - "is-electron@npm:^2.2.0": version: 2.2.2 resolution: "is-electron@npm:2.2.2" @@ -11159,17 +14103,6 @@ __metadata: languageName: node linkType: hard -"is-inside-container@npm:^1.0.0": - version: 1.0.0 - resolution: "is-inside-container@npm:1.0.0" - dependencies: - is-docker: "npm:^3.0.0" - bin: - is-inside-container: cli.js - checksum: a8efb0e84f6197e6ff5c64c52890fa9acb49b7b74fed4da7c95383965da6f0fa592b4dbd5e38a79f87fc108196937acdbcd758fcefc9b140e479b39ce1fcd1cd - languageName: node - linkType: hard - "is-interactive@npm:^1.0.0": version: 1.0.0 resolution: "is-interactive@npm:1.0.0" @@ -11193,10 +14126,19 @@ __metadata: languageName: node linkType: hard -"is-negative-zero@npm:^2.0.2": +"is-lower-case@npm:^2.0.2": version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: eda024c158f70f2017f3415e471b818d314da5ef5be68f801b16314d4a4b6304a74cbed778acf9e2f955bb9c1c5f2935c1be0c7c99e1ad12286f45366217b6a3 + resolution: "is-lower-case@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: c045e6a52dcc7c3857e2f8c850ded604cdc5269ff94625b03881cefc73bfc02f5099a1bc9bafa67793656711a40d4ab3e26e285a848e728506df20ead0ce8e2f + languageName: node + linkType: hard + +"is-negative-zero@npm:^2.0.2": + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: bcdcf6b8b9714063ffcfa9929c575ac69bfdabb8f4574ff557dfc086df2836cf07e3906f5bbc4f2a5c12f8f3ba56af640c843cdfc74da8caed86c7c7d66fd08e languageName: node linkType: hard @@ -11286,12 +14228,21 @@ __metadata: languageName: node linkType: hard +"is-relative@npm:^1.0.0": + version: 1.0.0 + resolution: "is-relative@npm:1.0.0" + dependencies: + is-unc-path: "npm:^1.0.0" + checksum: 61157c4be8594dd25ac6f0ef29b1218c36667259ea26698367a4d9f39ff9018368bc365c490b3c79be92dfb1e389e43c4b865c95709e7b3bc72c5932f751fb60 + languageName: node + linkType: hard + "is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" dependencies: - call-bind: "npm:^1.0.2" - checksum: cfeee6f171f1b13e6cbc6f3b6cc44e192b93df39f3fcb31aa66ffb1d2df3b91e05664311659f9701baba62f5e98c83b0673c628e7adc30f55071c4874fcdccec + call-bind: "npm:^1.0.7" + checksum: adc11ab0acbc934a7b9e5e9d6c588d4ec6682f6fea8cda5180721704fa32927582ede5b123349e32517fdadd07958973d24716c80e7ab198970c47acc09e59c7 languageName: node linkType: hard @@ -11309,13 +14260,6 @@ __metadata: languageName: node linkType: hard -"is-stream@npm:^3.0.0": - version: 3.0.0 - resolution: "is-stream@npm:3.0.0" - checksum: eb2f7127af02ee9aa2a0237b730e47ac2de0d4e76a4a905a50a11557f2339df5765eaea4ceb8029f1efa978586abe776908720bfcb1900c20c6ec5145f6f29d8 - languageName: node - linkType: hard - "is-string@npm:^1.0.5, is-string@npm:^1.0.7": version: 1.0.7 resolution: "is-string@npm:1.0.7" @@ -11325,6 +14269,15 @@ __metadata: languageName: node linkType: hard +"is-subdir@npm:^1.1.1": + version: 1.2.0 + resolution: "is-subdir@npm:1.2.0" + dependencies: + better-path-resolve: "npm:1.0.0" + checksum: 03a03ee2ee6578ce589b1cfaf00e65c86b20fd1b82c1660625557c535439a7477cda77e20c62cda6d4c99e7fd908b4619355ae2d989f4a524a35350a44353032 + languageName: node + linkType: hard + "is-symbol@npm:^1.0.2, is-symbol@npm:^1.0.3": version: 1.0.4 resolution: "is-symbol@npm:1.0.4" @@ -11343,12 +14296,12 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.3, is-typed-array@npm:^1.1.9": - version: 1.1.12 - resolution: "is-typed-array@npm:1.1.12" +"is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.3": + version: 1.1.13 + resolution: "is-typed-array@npm:1.1.13" dependencies: - which-typed-array: "npm:^1.1.11" - checksum: 9863e9cc7223c6fc1c462a2c3898a7beff6b41b1ee0fabb03b7d278ae7de670b5bcbc8627db56bb66ed60902fa37d53fe5cce0fd2f7d73ac64fe5da6f409b6ae + which-typed-array: "npm:^1.1.14" + checksum: fa5cb97d4a80e52c2cc8ed3778e39f175a1a2ae4ddf3adae3187d69586a1fd57cfa0b095db31f66aa90331e9e3da79184cea9c6abdcd1abc722dc3c3edd51cca languageName: node linkType: hard @@ -11359,6 +14312,15 @@ __metadata: languageName: node linkType: hard +"is-unc-path@npm:^1.0.0": + version: 1.0.0 + resolution: "is-unc-path@npm:1.0.0" + dependencies: + unc-path-regex: "npm:^0.1.2" + checksum: ac1b78f9b748196e3be3d0e722cd4b0f98639247a130a8f2473a58b29baf63fdb1b1c5a12c830660c5ee6ef0279c5418ca8e346f98cbe1a29e433d7ae531d42e + languageName: node + linkType: hard + "is-unicode-supported@npm:^0.1.0": version: 0.1.0 resolution: "is-unicode-supported@npm:0.1.0" @@ -11366,6 +14328,15 @@ __metadata: languageName: node linkType: hard +"is-upper-case@npm:^2.0.2": + version: 2.0.2 + resolution: "is-upper-case@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 2236f416484a2643d55a07cc95443cecf96cbc5fb0de7f24c506a8bc5cc4c4de885ab56c5ec946eadd95b3b7960bff7ed51cc88511fa8e8a9d92f2f8969622d9 + languageName: node + linkType: hard + "is-url@npm:^1.2.4": version: 1.2.4 resolution: "is-url@npm:1.2.4" @@ -11389,14 +14360,14 @@ __metadata: languageName: node linkType: hard -"is-windows@npm:^1.0.2": +"is-windows@npm:^1.0.0, is-windows@npm:^1.0.1, is-windows@npm:^1.0.2": version: 1.0.2 resolution: "is-windows@npm:1.0.2" checksum: b32f418ab3385604a66f1b7a3ce39d25e8881dee0bd30816dc8344ef6ff9df473a732bcc1ec4e84fe99b2f229ae474f7133e8e93f9241686cfcf7eebe53ba7a5 languageName: node linkType: hard -"is-wsl@npm:^2.1.1, is-wsl@npm:^2.2.0": +"is-wsl@npm:^2.1.1": version: 2.2.0 resolution: "is-wsl@npm:2.2.0" dependencies: @@ -11490,6 +14461,15 @@ __metadata: languageName: node linkType: hard +"isomorphic-ws@npm:5.0.0, isomorphic-ws@npm:^5.0.0": + version: 5.0.0 + resolution: "isomorphic-ws@npm:5.0.0" + peerDependencies: + ws: "*" + checksum: a058ac8b5e6efe9e46252cb0bc67fd325005d7216451d1a51238bc62d7da8486f828ef017df54ddf742e0fffcbe4b1bcc2a66cc115b027ed0180334cd18df252 + languageName: node + linkType: hard + "isstream@npm:~0.1.2": version: 0.1.2 resolution: "isstream@npm:0.1.2" @@ -11654,7 +14634,7 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:3.x, js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.0": +"js-yaml@npm:3.x, js-yaml@npm:^3.13.0, js-yaml@npm:^3.13.1, js-yaml@npm:^3.14.0, js-yaml@npm:^3.6.1": version: 3.14.1 resolution: "js-yaml@npm:3.14.1" dependencies: @@ -11677,6 +14657,13 @@ __metadata: languageName: node linkType: hard +"jsbn@npm:1.1.0": + version: 1.1.0 + resolution: "jsbn@npm:1.1.0" + checksum: 4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 + languageName: node + linkType: hard + "jsbn@npm:~0.1.0": version: 0.1.1 resolution: "jsbn@npm:0.1.1" @@ -11693,6 +14680,15 @@ __metadata: languageName: node linkType: hard +"jsesc@npm:^2.5.1": + version: 2.5.2 + resolution: "jsesc@npm:2.5.2" + bin: + jsesc: bin/jsesc + checksum: dbf59312e0ebf2b4405ef413ec2b25abb5f8f4d9bc5fb8d9f90381622ebca5f2af6a6aa9a8578f65903f9e33990a6dc798edd0ce5586894bf0e9e31803a1de88 + languageName: node + linkType: hard + "jsesc@npm:~0.5.0": version: 0.5.0 resolution: "jsesc@npm:0.5.0" @@ -11702,6 +14698,13 @@ __metadata: languageName: node linkType: hard +"json-bigint-patch@npm:^0.0.8": + version: 0.0.8 + resolution: "json-bigint-patch@npm:0.0.8" + checksum: f2ee19607c4927d1b0f1fda2f3c3cdba1162d1a7f6a40ae5e3e034363cddd437a0ef48d975e1e572dc514a7396ab2247b443113444004f1e64af47ba298687b9 + languageName: node + linkType: hard + "json-buffer@npm:3.0.0": version: 3.0.0 resolution: "json-buffer@npm:3.0.0" @@ -11723,6 +14726,15 @@ __metadata: languageName: node linkType: hard +"json-pointer@npm:0.6.2": + version: 0.6.2 + resolution: "json-pointer@npm:0.6.2" + dependencies: + foreach: "npm:^2.0.4" + checksum: 47f6103032c0340b3392cb650e0ec817f785eccb553407da13fae85bc535483c9b359d7e756de4ed73130172c28d2b02f8beb53a700a98b12e72c7bf70e734b7 + languageName: node + linkType: hard + "json-rpc-engine@npm:^3.4.0, json-rpc-engine@npm:^3.6.0": version: 3.8.0 resolution: "json-rpc-engine@npm:3.8.0" @@ -11753,6 +14765,17 @@ __metadata: languageName: node linkType: hard +"json-schema-to-ts@npm:^2.7.2": + version: 2.12.0 + resolution: "json-schema-to-ts@npm:2.12.0" + dependencies: + "@babel/runtime": "npm:^7.18.3" + "@types/json-schema": "npm:^7.0.9" + ts-algebra: "npm:^1.2.2" + checksum: e6aabb8470983e8242ae3120fa2a411f36d0e3cb12e37e838a2955edee9e26a412010a33bc01617e51b0b3df758c7a50a4d9b470070b22bca276f8056b5a8ed4 + languageName: node + linkType: hard + "json-schema-traverse@npm:^0.4.1": version: 0.4.1 resolution: "json-schema-traverse@npm:0.4.1" @@ -11782,14 +14805,14 @@ __metadata: linkType: hard "json-stable-stringify@npm:^1.0.1": - version: 1.1.0 - resolution: "json-stable-stringify@npm:1.1.0" + version: 1.1.1 + resolution: "json-stable-stringify@npm:1.1.1" dependencies: call-bind: "npm:^1.0.5" isarray: "npm:^2.0.5" jsonify: "npm:^0.0.1" object-keys: "npm:^1.1.1" - checksum: 8888ac86dbf55c1d494bdf40705171c30884686911c37383d3aab777754bf5c1d60dc7a4dfd67f32ba37b184da5c99948a382f1c2912895a35453002e253314b + checksum: 3801e3eeccbd030afb970f54bea690a079cfea7d9ed206a1b17ca9367f4b7772c764bf77a48f03e56b50e5f7ee7d11c52339fe20d8d7ccead003e4ca69e4cfde languageName: node linkType: hard @@ -11818,6 +14841,15 @@ __metadata: languageName: node linkType: hard +"json5@npm:^2.2.2, json5@npm:^2.2.3": + version: 2.2.3 + resolution: "json5@npm:2.2.3" + bin: + json5: lib/cli.js + checksum: 5a04eed94810fa55c5ea138b2f7a5c12b97c3750bc63d11e511dcecbfef758003861522a070c2272764ee0f4e3e323862f386945aeb5b85b87ee43f084ba586c + languageName: node + linkType: hard + "jsonfile@npm:^2.1.0": version: 2.4.0 resolution: "jsonfile@npm:2.4.0" @@ -11975,6 +15007,13 @@ __metadata: languageName: node linkType: hard +"kleur@npm:^4.1.5": + version: 4.1.5 + resolution: "kleur@npm:4.1.5" + checksum: e9de6cb49657b6fa70ba2d1448fd3d691a5c4370d8f7bbf1c2f64c24d461270f2117e1b0afe8cb3114f13bbd8e51de158c2a224953960331904e636a5e4c0f2a + languageName: node + linkType: hard + "kuler@npm:^2.0.0": version: 2.0.0 resolution: "kuler@npm:2.0.0" @@ -11982,6 +15021,15 @@ __metadata: languageName: node linkType: hard +"latest-version@npm:^7.0.0": + version: 7.0.0 + resolution: "latest-version@npm:7.0.0" + dependencies: + package-json: "npm:^8.1.0" + checksum: 68045f5e419e005c12e595ae19687dd88317dd0108b83a8773197876622c7e9d164fe43aacca4f434b2cba105c92848b89277f658eabc5d50e81fb743bbcddb1 + languageName: node + linkType: hard + "lcid@npm:^1.0.0": version: 1.0.0 resolution: "lcid@npm:1.0.0" @@ -12154,12 +15202,13 @@ __metadata: linkType: hard "level@npm:^8.0.0": - version: 8.0.0 - resolution: "level@npm:8.0.0" + version: 8.0.1 + resolution: "level@npm:8.0.1" dependencies: + abstract-level: "npm:^1.0.4" browser-level: "npm:^1.0.1" classic-level: "npm:^1.2.0" - checksum: 5259de90a48448b8bf097c148548443dd1a2107c670a7d77df1c36ed5e226edb6ef9ccc35fd8ee13e0924e48a1563ab8f1af8a2f24c7e614a8c1541e8edf6701 + checksum: 52e3c18a3372f22b7c0c96a998a24099454f51952ba2b8f25eabc72b1f7bbc15a3ab480c92c94d3c931be370be5a235b804b16e565b73b22bea52cca4029a625 languageName: node linkType: hard @@ -12210,6 +15259,15 @@ __metadata: languageName: node linkType: hard +"lie@npm:3.1.1": + version: 3.1.1 + resolution: "lie@npm:3.1.1" + dependencies: + immediate: "npm:~3.0.5" + checksum: d62685786590351b8e407814acdd89efe1cb136f05cb9236c5a97b2efdca1f631d2997310ad2d565c753db7596799870140e4777c9c9b8c44a0f6bf42d1804a1 + languageName: node + linkType: hard + "lines-and-columns@npm:^1.1.6": version: 1.2.4 resolution: "lines-and-columns@npm:1.2.4" @@ -12276,6 +15334,27 @@ __metadata: languageName: node linkType: hard +"load-yaml-file@npm:^0.2.0": + version: 0.2.0 + resolution: "load-yaml-file@npm:0.2.0" + dependencies: + graceful-fs: "npm:^4.1.5" + js-yaml: "npm:^3.13.0" + pify: "npm:^4.0.1" + strip-bom: "npm:^3.0.0" + checksum: e00ed43048c0648dfef7639129b6d7e5c2272bc36d2a50dd983dd495f3341a02cd2c40765afa01345f798d0d894e5ba53212449933e72ddfa4d3f7a48f822d2f + languageName: node + linkType: hard + +"localforage@npm:1.10.0": + version: 1.10.0 + resolution: "localforage@npm:1.10.0" + dependencies: + lie: "npm:3.1.1" + checksum: 00f19f1f97002e6721587ed5017f502d58faf80dae567d5065d4d1ee0caf0762f40d2e2dba7f0ef7d3f14ee6203242daae9ecad97359bfc10ecff36df11d85a3 + languageName: node + linkType: hard + "locate-path@npm:^2.0.0": version: 2.0.0 resolution: "locate-path@npm:2.0.0" @@ -12318,6 +15397,13 @@ __metadata: languageName: node linkType: hard +"lodash.clone@npm:^4.5.0": + version: 4.5.0 + resolution: "lodash.clone@npm:4.5.0" + checksum: e9e84b8727a24b6bdc6292dc0ff53fbdd379a65c652d9ba7a2cc3c02fb1c135b8dcd2e154c8c4199d4be7410d6f7ce3298df312822bc0e68f00472ec07da7d6d + languageName: node + linkType: hard + "lodash.clonedeep@npm:^4.5.0": version: 4.5.0 resolution: "lodash.clonedeep@npm:4.5.0" @@ -12325,6 +15411,13 @@ __metadata: languageName: node linkType: hard +"lodash.get@npm:4.4.2, lodash.get@npm:^4.4.2": + version: 4.4.2 + resolution: "lodash.get@npm:4.4.2" + checksum: 48f40d471a1654397ed41685495acb31498d5ed696185ac8973daef424a749ca0c7871bf7b665d5c14f5cc479394479e0307e781f61d5573831769593411be6e + languageName: node + linkType: hard + "lodash.isequal@npm:^4.5.0": version: 4.5.0 resolution: "lodash.isequal@npm:4.5.0" @@ -12388,6 +15481,13 @@ __metadata: languageName: node linkType: hard +"lodash.topath@npm:^4.5.2": + version: 4.5.2 + resolution: "lodash.topath@npm:4.5.2" + checksum: f555a1459c11c807517be6c3a3e8030a9e92a291b2d6b598511e0bddbe99297e870b20e097019b613a3035d061bac63cb42621386c0b9dc22fd3d85e58459653 + languageName: node + linkType: hard + "lodash.truncate@npm:^4.4.2": version: 4.4.2 resolution: "lodash.truncate@npm:4.4.2" @@ -12416,7 +15516,7 @@ __metadata: languageName: node linkType: hard -"lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21, lodash@npm:^4.17.4": +"lodash@npm:^4.17.11, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.21, lodash@npm:^4.17.4, lodash@npm:~4.17.0": version: 4.17.21 resolution: "lodash@npm:4.17.21" checksum: d8cbea072bb08655bb4c989da418994b073a608dffa608b09ac04b43a791b12aeae7cd7ad919aa4c925f33b48490b5cfe6c1f71d827956071dae2e7bb3a6b74c @@ -12493,6 +15593,24 @@ __metadata: languageName: node linkType: hard +"lower-case-first@npm:^2.0.2": + version: 2.0.2 + resolution: "lower-case-first@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 22253389fa0693ec1ba09b9394be3a8228304bf21d074703db2eef97c16cda9c66462d88f9b91d4ad0186493d23cad99c63d38ebc13f9a808bc83aad539ff404 + languageName: node + linkType: hard + +"lower-case@npm:^2.0.2": + version: 2.0.2 + resolution: "lower-case@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 3d925e090315cf7dc1caa358e0477e186ffa23947740e4314a7429b6e62d72742e0bbe7536a5ae56d19d7618ce998aba05caca53c2902bd5742fdca5fc57fd7b + languageName: node + linkType: hard + "lowercase-keys@npm:^1.0.0, lowercase-keys@npm:^1.0.1": version: 1.0.1 resolution: "lowercase-keys@npm:1.0.1" @@ -12523,10 +15641,10 @@ __metadata: languageName: node linkType: hard -"lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": - version: 10.1.0 - resolution: "lru-cache@npm:10.1.0" - checksum: 778bc8b2626daccd75f24c4b4d10632496e21ba064b126f526c626fbdbc5b28c472013fccd45d7646b9e1ef052444824854aed617b59cd570d01a8b7d651fc1e +"lru-cache@npm:^10.0.0, lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": + version: 10.2.0 + resolution: "lru-cache@npm:10.2.0" + checksum: c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee languageName: node linkType: hard @@ -12539,6 +15657,16 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^4.0.1": + version: 4.1.5 + resolution: "lru-cache@npm:4.1.5" + dependencies: + pseudomap: "npm:^1.0.2" + yallist: "npm:^2.1.2" + checksum: 1ca5306814e5add9ec63556d6fd9b24a4ecdeaef8e9cea52cbf30301e6b88c8d8ddc7cab45b59b56eb763e6c45af911585dc89925a074ab65e1502e3fe8103cf + languageName: node + linkType: hard + "lru-cache@npm:^6.0.0": version: 6.0.0 resolution: "lru-cache@npm:6.0.0" @@ -12548,6 +15676,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^7.14.1": + version: 7.18.3 + resolution: "lru-cache@npm:7.18.3" + checksum: b3a452b491433db885beed95041eb104c157ef7794b9c9b4d647be503be91769d11206bb573849a16b4cc0d03cbd15ffd22df7960997788b74c1d399ac7a4fed + languageName: node + linkType: hard + "lru_map@npm:^0.3.3": version: 0.3.3 resolution: "lru_map@npm:0.3.3" @@ -12595,7 +15730,7 @@ __metadata: languageName: node linkType: hard -"map-cache@npm:^0.2.2": +"map-cache@npm:^0.2.0, map-cache@npm:^0.2.2": version: 0.2.2 resolution: "map-cache@npm:0.2.2" checksum: 05e3eb005c1b80b9f949ca007687640e8c5d0fc88dc45c3c3ab4902a3bec79d66a58f3e3b04d6985d90cd267c629c7b46c977e9c34433e8c11ecfcbb9f0fa290 @@ -12632,6 +15767,13 @@ __metadata: languageName: node linkType: hard +"match-all@npm:^1.2.6": + version: 1.2.6 + resolution: "match-all@npm:1.2.6" + checksum: 4e0344bf3c39fdedf212bc0e61ce970a40f7f5c1cbbf34de0992a47515d999dab3aa8600a2a09487afb5f561e59d267f0b5dd7a74dfaec203cec77c1f8c52d5a + languageName: node + linkType: hard + "mcl-wasm@npm:^0.7.1": version: 0.7.9 resolution: "mcl-wasm@npm:0.7.9" @@ -12710,6 +15852,25 @@ __metadata: languageName: node linkType: hard +"meow@npm:^6.0.0": + version: 6.1.1 + resolution: "meow@npm:6.1.1" + dependencies: + "@types/minimist": "npm:^1.2.0" + camelcase-keys: "npm:^6.2.2" + decamelize-keys: "npm:^1.1.0" + hard-rejection: "npm:^2.1.0" + minimist-options: "npm:^4.0.2" + normalize-package-data: "npm:^2.5.0" + read-pkg-up: "npm:^7.0.1" + redent: "npm:^3.0.0" + trim-newlines: "npm:^3.0.0" + type-fest: "npm:^0.13.1" + yargs-parser: "npm:^18.1.3" + checksum: ceece1e5e09a53d7bf298ef137477e395a0dd30c8ed1a9980a52caad02eccffd6bce1a5cad4596cd694e7e924e949253f0cc1e7c22073c07ce7b06cfefbcf8be + languageName: node + linkType: hard + "meow@npm:^8.0.0": version: 8.1.2 resolution: "meow@npm:8.1.2" @@ -12790,6 +15951,18 @@ __metadata: languageName: node linkType: hard +"meros@npm:^1.2.1": + version: 1.3.0 + resolution: "meros@npm:1.3.0" + peerDependencies: + "@types/node": ">=13" + peerDependenciesMeta: + "@types/node": + optional: true + checksum: 2cf9a31228ae6441428a750b67beafec062cc0d693942045336dbe6bfb44507e0ca42854a46f483ebd97e4d78cbc31322b3b85f9648b60fa7a4b28fc0f858f51 + languageName: node + linkType: hard + "methods@npm:~1.1.2": version: 1.1.2 resolution: "methods@npm:1.1.2" @@ -12879,13 +16052,6 @@ __metadata: languageName: node linkType: hard -"mimic-fn@npm:^4.0.0": - version: 4.0.0 - resolution: "mimic-fn@npm:4.0.0" - checksum: de9cc32be9996fd941e512248338e43407f63f6d497abe8441fa33447d922e927de54d4cc3c1a3c6d652857acd770389d5a3823f311a744132760ce2be15ccbf - languageName: node - linkType: hard - "mimic-response@npm:^1.0.0, mimic-response@npm:^1.0.1": version: 1.0.1 resolution: "mimic-response@npm:1.0.1" @@ -12900,6 +16066,13 @@ __metadata: languageName: node linkType: hard +"mimic-response@npm:^4.0.0": + version: 4.0.0 + resolution: "mimic-response@npm:4.0.0" + checksum: 761d788d2668ae9292c489605ffd4fad220f442fbae6832adce5ebad086d691e906a6d5240c290293c7a11e99fbdbbef04abbbed498bf8699a4ee0f31315e3fb + languageName: node + linkType: hard + "min-document@npm:^2.19.0": version: 2.19.0 resolution: "min-document@npm:2.19.0" @@ -12930,7 +16103,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:*, minimatch@npm:^9.0.1": +"minimatch@npm:*, minimatch@npm:9.0.3, minimatch@npm:^9.0.1": version: 9.0.3 resolution: "minimatch@npm:9.0.3" dependencies: @@ -12966,7 +16139,7 @@ __metadata: languageName: node linkType: hard -"minimist-options@npm:4.1.0": +"minimist-options@npm:4.1.0, minimist-options@npm:^4.0.2": version: 4.1.0 resolution: "minimist-options@npm:4.1.0" dependencies: @@ -13097,6 +16270,13 @@ __metadata: languageName: node linkType: hard +"mixme@npm:^0.5.1": + version: 0.5.10 + resolution: "mixme@npm:0.5.10" + checksum: 409b2124b75b5f489b1521bc470f6201d748499bf656db0aa43a07e654449f3bcc8a0277cd05ca3c3e305281a5934b6e75219866200b70a9e3e105f9cf08baf1 + languageName: node + linkType: hard + "mkdirp-promise@npm:^5.0.1": version: 5.0.1 resolution: "mkdirp-promise@npm:5.0.1" @@ -13106,7 +16286,7 @@ __metadata: languageName: node linkType: hard -"mkdirp@npm:*": +"mkdirp@npm:*, mkdirp@npm:^3.0.0": version: 3.0.1 resolution: "mkdirp@npm:3.0.1" bin: @@ -13145,8 +16325,8 @@ __metadata: linkType: hard "mocha@npm:^10.0.0, mocha@npm:^10.2.0": - version: 10.2.0 - resolution: "mocha@npm:10.2.0" + version: 10.3.0 + resolution: "mocha@npm:10.3.0" dependencies: ansi-colors: "npm:4.1.1" browser-stdout: "npm:1.3.1" @@ -13155,13 +16335,12 @@ __metadata: diff: "npm:5.0.0" escape-string-regexp: "npm:4.0.0" find-up: "npm:5.0.0" - glob: "npm:7.2.0" + glob: "npm:8.1.0" he: "npm:1.2.0" js-yaml: "npm:4.1.0" log-symbols: "npm:4.1.0" minimatch: "npm:5.0.1" ms: "npm:2.1.3" - nanoid: "npm:3.3.3" serialize-javascript: "npm:6.0.0" strip-json-comments: "npm:3.1.1" supports-color: "npm:8.1.1" @@ -13172,7 +16351,7 @@ __metadata: bin: _mocha: bin/_mocha mocha: bin/mocha.js - checksum: 145185435535ec7766932e9fa3def1520ffb895e7fa341e8592829844c4c9dd9fcb35db139d448c228b5ad3c2bedce50423ce760827b3054fafe6d47ef014937 + checksum: 8dc93842468b2be5f820e5eb64208fb68ba3e5ee90cfe21a9f1d439f9ec031e8a8dc97f4d3206a376c9e05141cf689a812aedcf4545f71f69b3e9a51f312ec4a languageName: node linkType: hard @@ -13205,18 +16384,18 @@ __metadata: linkType: hard "moment-timezone@npm:^0.5.34, moment-timezone@npm:^0.5.43": - version: 0.5.43 - resolution: "moment-timezone@npm:0.5.43" + version: 0.5.45 + resolution: "moment-timezone@npm:0.5.45" dependencies: moment: "npm:^2.29.4" - checksum: 6f42174e01398d135883fb45aa820e57f34b25aab5ea6c50998139d06f975ee4457275b5e331466b14bff4d830e681c267f9cc462f445eb9c2b84d04add829f6 + checksum: 7497f23c4b8c875dbf07c03f9a1253f79edaeedc29d5732e36bfd3c5577e25aed1924fbd84cbb713ce1920dbe822be0e21bd487851a7d13907226f289a5e568b languageName: node linkType: hard "moment@npm:^2.29.1, moment@npm:^2.29.4": - version: 2.29.4 - resolution: "moment@npm:2.29.4" - checksum: 844c6f3ce42862ac9467c8ca4f5e48a00750078682cc5bda1bc0e50cc7ca88e2115a0f932d65a06e4a90e26cb78892be9b3ca3dd6546ca2c4d994cebb787fc2b + version: 2.30.1 + resolution: "moment@npm:2.30.1" + checksum: 865e4279418c6de666fca7786607705fd0189d8a7b7624e2e56be99290ac846f90878a6f602e34b4e0455c549b85385b1baf9966845962b313699e7cb847543a languageName: node linkType: hard @@ -13411,6 +16590,17 @@ __metadata: languageName: node linkType: hard +"murmur-128@npm:^0.2.1": + version: 0.2.1 + resolution: "murmur-128@npm:0.2.1" + dependencies: + encode-utf8: "npm:^1.0.2" + fmix: "npm:^0.1.0" + imul: "npm:^1.0.0" + checksum: 1ae871af53693a9159794b92ace63c1b5c1cc137d235cc954a56af00e48856625131605517e1ee00f60295d0223a13091b88d33a55686011774a63db3b94ecd5 + languageName: node + linkType: hard + "murmurhash3js-revisited@npm:^3.0.0": version: 3.0.0 resolution: "murmurhash3js-revisited@npm:3.0.0" @@ -13432,15 +16622,6 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:3.3.3": - version: 3.3.3 - resolution: "nanoid@npm:3.3.3" - bin: - nanoid: bin/nanoid.cjs - checksum: d7ab68893cdb92dd2152d505e56571d571c65b71a9815f9dfb3c9a8cbf943fe43c9777d9a95a3b81ef01e442fec8409a84375c08f90a5753610a9f22672d953a - languageName: node - linkType: hard - "nanoid@npm:^3.0.2, nanoid@npm:^3.1.3": version: 3.3.7 resolution: "nanoid@npm:3.3.7" @@ -13527,6 +16708,16 @@ __metadata: languageName: node linkType: hard +"no-case@npm:^3.0.4": + version: 3.0.4 + resolution: "no-case@npm:3.0.4" + dependencies: + lower-case: "npm:^2.0.2" + tslib: "npm:^2.0.3" + checksum: 8ef545f0b3f8677c848f86ecbd42ca0ff3cd9dd71c158527b344c69ba14710d816d8489c746b6ca225e7b615108938a0bda0a54706f8c255933703ac1cf8e703 + languageName: node + linkType: hard + "node-addon-api@npm:^2.0.0": version: 2.0.2 resolution: "node-addon-api@npm:2.0.2" @@ -13584,13 +16775,13 @@ __metadata: linkType: hard "node-gyp-build@npm:^4.2.0, node-gyp-build@npm:^4.3.0": - version: 4.7.1 - resolution: "node-gyp-build@npm:4.7.1" + version: 4.8.0 + resolution: "node-gyp-build@npm:4.8.0" bin: node-gyp-build: bin.js node-gyp-build-optional: optional.js node-gyp-build-test: build-test.js - checksum: b8e4a3f889237cd08edde3775e2b4e1e39a0571580584e33e29979f0c532a254ce3c5ec9435bd526254ad0b3f0b4a7e7fe14e53bd400f6ea9445f3bfd88a6b1e + checksum: 85324be16f81f0235cbbc42e3eceaeb1b5ab94c8d8f5236755e1435b4908338c65a4e75f66ee343cbcb44ddf9b52a428755bec16dcd983295be4458d95c8e1ad languageName: node linkType: hard @@ -13614,6 +16805,20 @@ __metadata: languageName: node linkType: hard +"node-int64@npm:^0.4.0": + version: 0.4.0 + resolution: "node-int64@npm:0.4.0" + checksum: a6a4d8369e2f2720e9c645255ffde909c0fbd41c92ea92a5607fc17055955daac99c1ff589d421eee12a0d24e99f7bfc2aabfeb1a4c14742f6c099a51863f31a + languageName: node + linkType: hard + +"node-releases@npm:^2.0.14": + version: 2.0.14 + resolution: "node-releases@npm:2.0.14" + checksum: 199fc93773ae70ec9969bc6d5ac5b2bbd6eb986ed1907d751f411fef3ede0e4bfdb45ceb43711f8078bea237b6036db8b1bf208f6ff2b70c7d615afd157f3ab9 + languageName: node + linkType: hard + "nofilter@npm:^3.1.0": version: 3.1.0 resolution: "nofilter@npm:3.1.0" @@ -13667,6 +16872,15 @@ __metadata: languageName: node linkType: hard +"normalize-path@npm:^2.1.1": + version: 2.1.1 + resolution: "normalize-path@npm:2.1.1" + dependencies: + remove-trailing-separator: "npm:^1.0.1" + checksum: db814326ff88057437233361b4c7e9cac7b54815b051b57f2d341ce89b1d8ec8cbd43e7fa95d7652b3b69ea8fcc294b89b8530d556a84d1bdace94229e1e9a8b + languageName: node + linkType: hard + "normalize-path@npm:^3.0.0, normalize-path@npm:~3.0.0": version: 3.0.0 resolution: "normalize-path@npm:3.0.0" @@ -13688,6 +16902,13 @@ __metadata: languageName: node linkType: hard +"normalize-url@npm:^8.0.0": + version: 8.0.0 + resolution: "normalize-url@npm:8.0.0" + checksum: 09582d56acd562d89849d9239852c2aff225c72be726556d6883ff36de50006803d32a023c10e917bcc1c55f73f3bb16434f67992fe9b61906a3db882192753c + languageName: node + linkType: hard + "npm-run-path@npm:^4.0.0, npm-run-path@npm:^4.0.1": version: 4.0.1 resolution: "npm-run-path@npm:4.0.1" @@ -13697,12 +16918,10 @@ __metadata: languageName: node linkType: hard -"npm-run-path@npm:^5.1.0": - version: 5.1.0 - resolution: "npm-run-path@npm:5.1.0" - dependencies: - path-key: "npm:^4.0.0" - checksum: ff6d77514489f47fa1c3b1311d09cd4b6d09a874cc1866260f9dea12cbaabda0436ed7f8c2ee44d147bf99a3af29307c6f63b0f83d242b0b6b0ab25dff2629e3 +"nullthrows@npm:^1.1.1": + version: 1.1.1 + resolution: "nullthrows@npm:1.1.1" + checksum: 56f34bd7c3dcb3bd23481a277fa22918120459d3e9d95ca72976c72e9cac33a97483f0b95fc420e2eb546b9fe6db398273aba9a938650cdb8c98ee8f159dcb30 languageName: node linkType: hard @@ -13748,7 +16967,14 @@ __metadata: languageName: node linkType: hard -"object-inspect@npm:^1.13.1, object-inspect@npm:^1.9.0": +"object-inspect@npm:1.10.3": + version: 1.10.3 + resolution: "object-inspect@npm:1.10.3" + checksum: 42bf0d9df02fba934148c9d30183c57c8327aa09deefbfa24b563019fe25678a49c96bdd2c9c14d9c21f067e73bc02d0d54861d72cefb53b29e5258b9455cc50 + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.1": version: 1.13.1 resolution: "object-inspect@npm:1.13.1" checksum: fad603f408e345c82e946abdf4bfd774260a5ed3e5997a0b057c44153ac32c7271ff19e3a5ae39c858da683ba045ccac2f65245c12763ce4e8594f818f4a648d @@ -13795,15 +17021,15 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.4": - version: 4.1.4 - resolution: "object.assign@npm:4.1.4" +"object.assign@npm:^4.1.5": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.1.4" + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" has-symbols: "npm:^1.0.3" object-keys: "npm:^1.1.1" - checksum: 2f286118c023e557757620e647b02e7c88d3d417e0c568fca0820de8ec9cca68928304854d5b03e99763eddad6e78a6716e2930f7e6372e4b9b843f3fd3056f3 + checksum: 60108e1fa2706f22554a4648299b0955236c62b3685c52abf4988d14fffb0e7731e00aa8c6448397e3eb63d087dcc124a9f21e1980f36d0b2667f3c18bacd469 languageName: node linkType: hard @@ -13913,15 +17139,6 @@ __metadata: languageName: node linkType: hard -"onetime@npm:^6.0.0": - version: 6.0.0 - resolution: "onetime@npm:6.0.0" - dependencies: - mimic-fn: "npm:^4.0.0" - checksum: 4eef7c6abfef697dd4479345a4100c382d73c149d2d56170a54a07418c50816937ad09500e1ed1e79d235989d073a9bade8557122aee24f0576ecde0f392bb6c - languageName: node - linkType: hard - "open@npm:^7.4.2": version: 7.4.2 resolution: "open@npm:7.4.2" @@ -13932,15 +17149,10 @@ __metadata: languageName: node linkType: hard -"open@npm:^9.1.0": - version: 9.1.0 - resolution: "open@npm:9.1.0" - dependencies: - default-browser: "npm:^4.0.0" - define-lazy-prop: "npm:^3.0.0" - is-inside-container: "npm:^1.0.0" - is-wsl: "npm:^2.2.0" - checksum: 8073ec0dd8994a7a7d9bac208bd17d093993a65ce10f2eb9b62b6d3a91c9366ae903938a237c275493c130171d339f6dcbdd2a2de7e32953452c0867b97825af +"openapi-types@npm:^12.1.0": + version: 12.1.3 + resolution: "openapi-types@npm:12.1.3" + checksum: 4ad4eb91ea834c237edfa6ab31394e87e00c888fc2918009763389c00d02342345195d6f302d61c3fd807f17723cd48df29b47b538b68375b3827b3758cd520f languageName: node linkType: hard @@ -13958,7 +17170,7 @@ __metadata: languageName: node linkType: hard -"optionator@npm:^0.9.1, optionator@npm:^0.9.3": +"optionator@npm:^0.9.3": version: 0.9.3 resolution: "optionator@npm:0.9.3" dependencies: @@ -14012,6 +17224,13 @@ __metadata: languageName: node linkType: hard +"outdent@npm:^0.5.0": + version: 0.5.0 + resolution: "outdent@npm:0.5.0" + checksum: e216a4498889ba1babae06af84cdc4091f7cac86da49d22d0163b3be202a5f52efcd2bcd3dfca60a361eb3a27b4299f185c5655061b6b402552d7fcd1d040cff + languageName: node + linkType: hard + "p-cancelable@npm:^1.0.0": version: 1.1.0 resolution: "p-cancelable@npm:1.1.0" @@ -14050,6 +17269,15 @@ __metadata: languageName: node linkType: hard +"p-filter@npm:^2.1.0": + version: 2.1.0 + resolution: "p-filter@npm:2.1.0" + dependencies: + p-map: "npm:^2.0.0" + checksum: 5ac34b74b3b691c04212d5dd2319ed484f591c557a850a3ffc93a08cb38c4f5540be059c6b10a185773c479ca583a91ea00c7d6c9958c815e6b74d052f356645 + languageName: node + linkType: hard + "p-finally@npm:^1.0.0": version: 1.0.0 resolution: "p-finally@npm:1.0.0" @@ -14057,6 +17285,15 @@ __metadata: languageName: node linkType: hard +"p-limit@npm:3.1.0, p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: "npm:^0.1.0" + checksum: 9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a + languageName: node + linkType: hard + "p-limit@npm:^1.1.0": version: 1.3.0 resolution: "p-limit@npm:1.3.0" @@ -14070,17 +17307,8 @@ __metadata: version: 2.3.0 resolution: "p-limit@npm:2.3.0" dependencies: - p-try: "npm:^2.0.0" - checksum: 8da01ac53efe6a627080fafc127c873da40c18d87b3f5d5492d465bb85ec7207e153948df6b9cbaeb130be70152f874229b8242ee2be84c0794082510af97f12 - languageName: node - linkType: hard - -"p-limit@npm:^3.0.2": - version: 3.1.0 - resolution: "p-limit@npm:3.1.0" - dependencies: - yocto-queue: "npm:^0.1.0" - checksum: 9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a + p-try: "npm:^2.0.0" + checksum: 8da01ac53efe6a627080fafc127c873da40c18d87b3f5d5492d465bb85ec7207e153948df6b9cbaeb130be70152f874229b8242ee2be84c0794082510af97f12 languageName: node linkType: hard @@ -14111,6 +17339,13 @@ __metadata: languageName: node linkType: hard +"p-map@npm:^2.0.0": + version: 2.1.0 + resolution: "p-map@npm:2.1.0" + checksum: 735dae87badd4737a2dd582b6d8f93e49a1b79eabbc9815a4d63a528d5e3523e978e127a21d784cccb637010e32103a40d2aaa3ab23ae60250b1a820ca752043 + languageName: node + linkType: hard + "p-map@npm:^4.0.0": version: 4.0.0 resolution: "p-map@npm:4.0.0" @@ -14120,7 +17355,7 @@ __metadata: languageName: node linkType: hard -"p-queue@npm:^6.6.1": +"p-queue@npm:^6.6.1, p-queue@npm:^6.6.2": version: 6.6.2 resolution: "p-queue@npm:6.6.2" dependencies: @@ -14153,6 +17388,18 @@ __metadata: languageName: node linkType: hard +"package-json@npm:^8.1.0": + version: 8.1.1 + resolution: "package-json@npm:8.1.1" + dependencies: + got: "npm:^12.1.0" + registry-auth-token: "npm:^5.0.1" + registry-url: "npm:^6.0.0" + semver: "npm:^7.3.7" + checksum: 83b057878bca229033aefad4ef51569b484e63a65831ddf164dc31f0486817e17ffcb58c819c7af3ef3396042297096b3ffc04e107fd66f8f48756f6d2071c8f + languageName: node + linkType: hard + "packet-reader@npm:1.0.0": version: 1.0.0 resolution: "packet-reader@npm:1.0.0" @@ -14160,6 +17407,16 @@ __metadata: languageName: node linkType: hard +"param-case@npm:^3.0.4": + version: 3.0.4 + resolution: "param-case@npm:3.0.4" + dependencies: + dot-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: ccc053f3019f878eca10e70ec546d92f51a592f762917dafab11c8b532715dcff58356118a6f350976e4ab109e321756f05739643ed0ca94298e82291e6f9e76 + languageName: node + linkType: hard + "parent-module@npm:^1.0.0": version: 1.0.1 resolution: "parent-module@npm:1.0.1" @@ -14196,6 +17453,17 @@ __metadata: languageName: node linkType: hard +"parse-filepath@npm:^1.0.2": + version: 1.0.2 + resolution: "parse-filepath@npm:1.0.2" + dependencies: + is-absolute: "npm:^1.0.0" + map-cache: "npm:^0.2.0" + path-root: "npm:^0.1.1" + checksum: 37bbd225fa864257246777efbdf72a9305c4ae12110bf467d11994e93f8be60dd309dcef68124a2c78c5d3b4e64e1c36fcc2560e2ea93fd97767831e7a446805 + languageName: node + linkType: hard + "parse-headers@npm:^2.0.0": version: 2.0.5 resolution: "parse-headers@npm:2.0.5" @@ -14231,6 +17499,16 @@ __metadata: languageName: node linkType: hard +"pascal-case@npm:^3.1.2": + version: 3.1.2 + resolution: "pascal-case@npm:3.1.2" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: 05ff7c344809fd272fc5030ae0ee3da8e4e63f36d47a1e0a4855ca59736254192c5a27b5822ed4bae96e54048eec5f6907713cfcfff7cdf7a464eaf7490786d8 + languageName: node + linkType: hard + "pascalcase@npm:^0.1.1": version: 0.1.1 resolution: "pascalcase@npm:0.1.1" @@ -14284,13 +17562,23 @@ __metadata: languageName: node linkType: hard -"path-browserify@npm:^1.0.0": +"path-browserify@npm:1.0.1, path-browserify@npm:^1.0.0": version: 1.0.1 resolution: "path-browserify@npm:1.0.1" checksum: 8b8c3fd5c66bd340272180590ae4ff139769e9ab79522e2eb82e3d571a89b8117c04147f65ad066dccfb42fcad902e5b7d794b3d35e0fd840491a8ddbedf8c66 languageName: node linkType: hard +"path-case@npm:^3.0.4": + version: 3.0.4 + resolution: "path-case@npm:3.0.4" + dependencies: + dot-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: b6b14637228a558793f603aaeb2fcd981e738b8b9319421b713532fba96d75aa94024b9f6b9ae5aa33d86755144a5b36697d28db62ae45527dbd672fcc2cf0b7 + languageName: node + linkType: hard + "path-exists@npm:^2.0.0": version: 2.1.0 resolution: "path-exists@npm:2.1.0" @@ -14335,13 +17623,6 @@ __metadata: languageName: node linkType: hard -"path-key@npm:^4.0.0": - version: 4.0.0 - resolution: "path-key@npm:4.0.0" - checksum: 794efeef32863a65ac312f3c0b0a99f921f3e827ff63afa5cb09a377e202c262b671f7b3832a4e64731003fa94af0263713962d317b9887bd1e0c48a342efba3 - languageName: node - linkType: hard - "path-parse@npm:^1.0.6, path-parse@npm:^1.0.7": version: 1.0.7 resolution: "path-parse@npm:1.0.7" @@ -14349,6 +17630,22 @@ __metadata: languageName: node linkType: hard +"path-root-regex@npm:^0.1.0": + version: 0.1.2 + resolution: "path-root-regex@npm:0.1.2" + checksum: 27651a234f280c70d982dd25c35550f74a4284cde6b97237aab618cb4b5745682d18cdde1160617bb4a4b6b8aec4fbc911c4a2ad80d01fa4c7ee74dae7af2337 + languageName: node + linkType: hard + +"path-root@npm:^0.1.1": + version: 0.1.1 + resolution: "path-root@npm:0.1.1" + dependencies: + path-root-regex: "npm:^0.1.0" + checksum: aed5cd290df84c46c7730f6a363e95e47a23929b51ab068a3818d69900da3e89dc154cdfd0c45c57b2e02f40c094351bc862db70c2cb00b7e6bd47039a227813 + languageName: node + linkType: hard + "path-scurry@npm:^1.10.1": version: 1.10.1 resolution: "path-scurry@npm:1.10.1" @@ -14544,6 +17841,13 @@ __metadata: languageName: node linkType: hard +"picomatch@npm:^4.0.1": + version: 4.0.1 + resolution: "picomatch@npm:4.0.1" + checksum: a036a085b18b376493e8ccef155bb03c65a2be7203582b717bb0498d1446e6a80f7f86a36e07877590abd0431f26c64c6154058c31f4f46105d3686a34fa3cf6 + languageName: node + linkType: hard + "pify@npm:^2.0.0, pify@npm:^2.3.0": version: 2.3.0 resolution: "pify@npm:2.3.0" @@ -14641,6 +17945,15 @@ __metadata: languageName: node linkType: hard +"pkg-dir@npm:^4.2.0": + version: 4.2.0 + resolution: "pkg-dir@npm:4.2.0" + dependencies: + find-up: "npm:^4.0.0" + checksum: c56bda7769e04907a88423feb320babaed0711af8c436ce3e56763ab1021ba107c7b0cafb11cde7529f669cfc22bffcaebffb573645cbd63842ea9fb17cd7728 + languageName: node + linkType: hard + "please-upgrade-node@npm:^3.2.0": version: 3.2.0 resolution: "please-upgrade-node@npm:3.2.0" @@ -14664,6 +17977,13 @@ __metadata: languageName: node linkType: hard +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: d9aa22d31f4f7680e20269db76791b41c3a32c01a373e25f8a4813b4d45f7456bfc2b6d68f752dc4aab0e0bb0721cb3d76fb678c9101cb7a16316664bc2c73fd + languageName: node + linkType: hard + "postgres-array@npm:~2.0.0": version: 2.0.0 resolution: "postgres-array@npm:2.0.0" @@ -14708,6 +18028,18 @@ __metadata: languageName: node linkType: hard +"preferred-pm@npm:^3.0.0": + version: 3.1.3 + resolution: "preferred-pm@npm:3.1.3" + dependencies: + find-up: "npm:^5.0.0" + find-yarn-workspace-root2: "npm:1.2.16" + path-exists: "npm:^4.0.0" + which-pm: "npm:2.0.0" + checksum: 8eb9c35e4818d8e20b5b61a2117f5c77678649e1d20492fe4fdae054a9c4b930d04582b17e8a59b2dc923f2f788c7ded7fc99fd22c04631d836f7f52aeb79bde + languageName: node + linkType: hard + "prelude-ls@npm:^1.2.1": version: 1.2.1 resolution: "prelude-ls@npm:1.2.1" @@ -14738,23 +18070,20 @@ __metadata: languageName: node linkType: hard -"prettier-plugin-solidity@npm:1.0.0-beta.19": - version: 1.0.0-beta.19 - resolution: "prettier-plugin-solidity@npm:1.0.0-beta.19" +"prettier-plugin-solidity@npm:^1.3.1": + version: 1.3.1 + resolution: "prettier-plugin-solidity@npm:1.3.1" dependencies: - "@solidity-parser/parser": "npm:^0.14.0" - emoji-regex: "npm:^10.0.0" - escape-string-regexp: "npm:^4.0.0" - semver: "npm:^7.3.5" - solidity-comments-extractor: "npm:^0.0.7" - string-width: "npm:^4.2.3" + "@solidity-parser/parser": "npm:^0.17.0" + semver: "npm:^7.5.4" + solidity-comments-extractor: "npm:^0.0.8" peerDependencies: - prettier: ^2.3.0 - checksum: f0fcfb61afeb3c9cda4bc0d49ddb81a730faa4398dd06459d39d1a93b345a2ab9eeb227b4f68c6278b19f053e4b4ac4ab239889691ac7924f620407ef698a426 + prettier: ">=2.3.0" + checksum: 6c83bec93a12a172aeae360bca571ffba5659a679d24d9a4905c4cae9f237a2a3c544a78f5efb7f2cd086733e114ed9e031d448799ca7b9f574e8fc07b94323a languageName: node linkType: hard -"prettier@npm:^2.1.2, prettier@npm:^2.2.1, prettier@npm:^2.8.3": +"prettier@npm:^2.1.2, prettier@npm:^2.7.1, prettier@npm:^2.8.3": version: 2.8.8 resolution: "prettier@npm:2.8.8" bin: @@ -14763,12 +18092,12 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^3.0.3": - version: 3.1.0 - resolution: "prettier@npm:3.1.0" +"prettier@npm:^3.0.3, prettier@npm:^3.2.5": + version: 3.2.5 + resolution: "prettier@npm:3.2.5" bin: prettier: bin/prettier.cjs - checksum: a45ea70aa97fde162ea4c4aba3dfc7859aa6a732a1db34458d9535dc3c2c16d3bc3fb5689e6cd76aa835562555303b02d9449fd2e15af3b73c8053557e25c5b6 + checksum: ea327f37a7d46f2324a34ad35292af2ad4c4c3c3355da07313339d7e554320f66f65f91e856add8530157a733c6c4a897dc41b577056be5c24c40f739f5ee8c6 languageName: node linkType: hard @@ -14807,13 +18136,6 @@ __metadata: languageName: node linkType: hard -"progress@npm:^2.0.0": - version: 2.0.3 - resolution: "progress@npm:2.0.3" - checksum: 1697e07cb1068055dbe9fe858d242368ff5d2073639e652b75a7eb1f2a1a8d4afd404d719de23c7b48481a6aa0040686310e2dac2f53d776daa2176d3f96369c - languageName: node - linkType: hard - "prom-client@npm:14.0.1": version: 14.0.1 resolution: "prom-client@npm:14.0.1" @@ -14852,6 +18174,15 @@ __metadata: languageName: node linkType: hard +"promise@npm:^7.1.1": + version: 7.3.1 + resolution: "promise@npm:7.3.1" + dependencies: + asap: "npm:~2.0.3" + checksum: 742e5c0cc646af1f0746963b8776299701ad561ce2c70b49365d62c8db8ea3681b0a1bf0d4e2fe07910bf72f02d39e51e8e73dc8d7503c3501206ac908be107f + languageName: node + linkType: hard + "promise@npm:^8.0.0": version: 8.3.0 resolution: "promise@npm:8.3.0" @@ -14881,6 +18212,13 @@ __metadata: languageName: node linkType: hard +"proto-list@npm:~1.2.1": + version: 1.2.4 + resolution: "proto-list@npm:1.2.4" + checksum: b9179f99394ec8a68b8afc817690185f3b03933f7b46ce2e22c1930dc84b60d09f5ad222beab4e59e58c6c039c7f7fcf620397235ef441a356f31f9744010e12 + languageName: node + linkType: hard + "protocol-buffers-schema@npm:^3.3.1": version: 3.6.0 resolution: "protocol-buffers-schema@npm:3.6.0" @@ -14924,7 +18262,7 @@ __metadata: languageName: node linkType: hard -"pseudomap@npm:^1.0.1": +"pseudomap@npm:^1.0.1, pseudomap@npm:^1.0.2": version: 1.0.2 resolution: "pseudomap@npm:1.0.2" checksum: 5a91ce114c64ed3a6a553aa7d2943868811377388bb31447f9d8028271bae9b05b340fe0b6961a64e45b9c72946aeb0a4ab635e8f7cb3715ffd0ff2beeb6a679 @@ -15042,7 +18380,7 @@ __metadata: languageName: node linkType: hard -"punycode@npm:^1.4.1": +"punycode@npm:^1.3.2, punycode@npm:^1.4.1": version: 1.4.1 resolution: "punycode@npm:1.4.1" checksum: 354b743320518aef36f77013be6e15da4db24c2b4f62c5f1eb0529a6ed02fbaf1cb52925785f6ab85a962f2b590d9cd5ad730b70da72b5f180e2556b8bd3ca08 @@ -15056,6 +18394,22 @@ __metadata: languageName: node linkType: hard +"pvtsutils@npm:^1.3.2, pvtsutils@npm:^1.3.5": + version: 1.3.5 + resolution: "pvtsutils@npm:1.3.5" + dependencies: + tslib: "npm:^2.6.1" + checksum: d425aed316907e0b447a459bfb97c55d22270c3cfdba5a07ec90da0737b0e40f4f1771a444636f85bb6a453de90ff8c6b5f4f6ddba7597977166af49974b4534 + languageName: node + linkType: hard + +"pvutils@npm:^1.1.3": + version: 1.1.3 + resolution: "pvutils@npm:1.1.3" + checksum: 23489e6b3c76b6afb6964a20f891d6bef092939f401c78bba186b2bfcdc7a13904a0af0a78f7933346510f8c1228d5ab02d3c80e968fd84d3c76ff98d8ec9aac + languageName: node + linkType: hard + "qs@npm:6.11.0": version: 6.11.0 resolution: "qs@npm:6.11.0" @@ -15079,7 +18433,7 @@ __metadata: languageName: node linkType: hard -"qs@npm:^6.11.2, qs@npm:^6.4.0, qs@npm:^6.7.0": +"qs@npm:^6.11.2, qs@npm:^6.4.0, qs@npm:^6.7.0, qs@npm:^6.9.4": version: 6.11.2 resolution: "qs@npm:6.11.2" dependencies: @@ -15208,6 +18562,43 @@ __metadata: languageName: node linkType: hard +"rc@npm:1.2.8": + version: 1.2.8 + resolution: "rc@npm:1.2.8" + dependencies: + deep-extend: "npm:^0.6.0" + ini: "npm:~1.3.0" + minimist: "npm:^1.2.0" + strip-json-comments: "npm:~2.0.1" + bin: + rc: ./cli.js + checksum: 24a07653150f0d9ac7168e52943cc3cb4b7a22c0e43c7dff3219977c2fdca5a2760a304a029c20811a0e79d351f57d46c9bde216193a0f73978496afc2b85b15 + languageName: node + linkType: hard + +"react-native-fs@npm:2.20.0": + version: 2.20.0 + resolution: "react-native-fs@npm:2.20.0" + dependencies: + base-64: "npm:^0.1.0" + utf8: "npm:^3.0.0" + peerDependencies: + react-native: "*" + react-native-windows: "*" + peerDependenciesMeta: + react-native-windows: + optional: true + checksum: 3722b5568610cd72f319c90f60ba8b019a005d015f27e49017ddd0ea314d1ea6991f79288c28549fdc2964dc81c0fa24f8a5f87a4a6283c97c6ea88d4caa6851 + languageName: node + linkType: hard + +"react-native-path@npm:0.0.5": + version: 0.0.5 + resolution: "react-native-path@npm:0.0.5" + checksum: 4dc98c7afd20dbf41b821d530e4bc8538408158e455807ee2d363ec5bbe8f6cf93bee24628cff5c96106e7f7bf35efc1c7d41ca86d0a24ce1063a3b8cf7c5a07 + languageName: node + linkType: hard + "read-pkg-up@npm:^1.0.1": version: 1.0.1 resolution: "read-pkg-up@npm:1.0.1" @@ -15252,6 +18643,18 @@ __metadata: languageName: node linkType: hard +"read-yaml-file@npm:^1.1.0": + version: 1.1.0 + resolution: "read-yaml-file@npm:1.1.0" + dependencies: + graceful-fs: "npm:^4.1.5" + js-yaml: "npm:^3.6.1" + pify: "npm:^4.0.1" + strip-bom: "npm:^3.0.0" + checksum: 85a9ba08bb93f3c91089bab4f1603995ec7156ee595f8ce40ae9f49d841cbb586511508bd47b7cf78c97f678c679b2c6e2c0092e63f124214af41b6f8a25ca31 + languageName: node + linkType: hard + "readable-stream@npm:2 || 3, readable-stream@npm:3, readable-stream@npm:^3.0.0, readable-stream@npm:^3.0.6, readable-stream@npm:^3.1.1, readable-stream@npm:^3.4.0, readable-stream@npm:^3.6.0, readable-stream@npm:^3.6.2": version: 3.6.2 resolution: "readable-stream@npm:3.6.2" @@ -15369,6 +18772,13 @@ __metadata: languageName: node linkType: hard +"regenerator-runtime@npm:^0.14.0": + version: 0.14.1 + resolution: "regenerator-runtime@npm:0.14.1" + checksum: 1b16eb2c4bceb1665c89de70dcb64126a22bc8eb958feef3cd68fe11ac6d2a4899b5cd1b80b0774c7c03591dc57d16631a7f69d2daa2ec98100e2f29f7ec4cc4 + languageName: node + linkType: hard + "regenerator-transform@npm:^0.10.0": version: 0.10.1 resolution: "regenerator-transform@npm:0.10.1" @@ -15390,21 +18800,15 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.1": - version: 1.5.1 - resolution: "regexp.prototype.flags@npm:1.5.1" +"regexp.prototype.flags@npm:^1.5.1, regexp.prototype.flags@npm:^1.5.2": + version: 1.5.2 + resolution: "regexp.prototype.flags@npm:1.5.2" dependencies: - call-bind: "npm:^1.0.2" - define-properties: "npm:^1.2.0" - set-function-name: "npm:^2.0.0" - checksum: 1de7d214c0a726c7c874a7023e47b0e27b9f7fdb64175bfe1861189de1704aaeca05c3d26c35aa375432289b99946f3cf86651a92a8f7601b90d8c226a23bcd8 - languageName: node - linkType: hard - -"regexpp@npm:^3.1.0": - version: 3.2.0 - resolution: "regexpp@npm:3.2.0" - checksum: d1da82385c8754a1681416b90b9cca0e21b4a2babef159099b88f640637d789c69011d0bc94705dacab85b81133e929d027d85210e8b8b03f8035164dbc14710 + call-bind: "npm:^1.0.6" + define-properties: "npm:^1.2.1" + es-errors: "npm:^1.3.0" + set-function-name: "npm:^2.0.1" + checksum: 0f3fc4f580d9c349f8b560b012725eb9c002f36daa0041b3fbf6f4238cb05932191a4d7d5db3b5e2caa336d5150ad0402ed2be81f711f9308fe7e1a9bf9bd552 languageName: node linkType: hard @@ -15419,6 +18823,24 @@ __metadata: languageName: node linkType: hard +"registry-auth-token@npm:^5.0.1": + version: 5.0.2 + resolution: "registry-auth-token@npm:5.0.2" + dependencies: + "@pnpm/npm-conf": "npm:^2.1.0" + checksum: 20fc2225681cc54ae7304b31ebad5a708063b1949593f02dfe5fb402bc1fc28890cecec6497ea396ba86d6cca8a8480715926dfef8cf1f2f11e6f6cc0a1b4bde + languageName: node + linkType: hard + +"registry-url@npm:^6.0.0": + version: 6.0.1 + resolution: "registry-url@npm:6.0.1" + dependencies: + rc: "npm:1.2.8" + checksum: 66e2221c8113fc35ee9d23fe58cb516fc8d556a189fb8d6f1011a02efccc846c4c9b5075b4027b99a5d5c9ad1345ac37f297bea3c0ca30d607ec8084bf561b90 + languageName: node + linkType: hard + "regjsgen@npm:^0.2.0": version: 0.2.0 resolution: "regjsgen@npm:0.2.0" @@ -15437,6 +18859,24 @@ __metadata: languageName: node linkType: hard +"relay-runtime@npm:12.0.0": + version: 12.0.0 + resolution: "relay-runtime@npm:12.0.0" + dependencies: + "@babel/runtime": "npm:^7.0.0" + fbjs: "npm:^3.0.0" + invariant: "npm:^2.2.4" + checksum: f5d29b5c2f3c8a3438d43dcbc3022bd454c4ecbd4f0b10616df08bedc62d8aaa84f155f23e374053cf9f4a8238b93804e37a5b37ed9dc7ad01436d62d1b01d53 + languageName: node + linkType: hard + +"remove-trailing-separator@npm:^1.0.1": + version: 1.1.0 + resolution: "remove-trailing-separator@npm:1.1.0" + checksum: 3568f9f8f5af3737b4aee9e6e1e8ec4be65a92da9cb27f989e0893714d50aa95ed2ff02d40d1fa35e1b1a234dc9c2437050ef356704a3999feaca6667d9e9bfc + languageName: node + linkType: hard + "repeat-element@npm:^1.1.2": version: 1.1.4 resolution: "repeat-element@npm:1.1.4" @@ -15534,6 +18974,13 @@ __metadata: languageName: node linkType: hard +"require-main-filename@npm:^2.0.0": + version: 2.0.0 + resolution: "require-main-filename@npm:2.0.0" + checksum: db91467d9ead311b4111cbd73a4e67fa7820daed2989a32f7023785a2659008c6d119752d9c4ac011ae07e537eb86523adff99804c5fdb39cd3a017f9b401bb6 + languageName: node + linkType: hard + "reset@npm:^0.1.0": version: 0.1.0 resolution: "reset@npm:0.1.0" @@ -15661,6 +19108,15 @@ __metadata: languageName: node linkType: hard +"responselike@npm:^3.0.0": + version: 3.0.0 + resolution: "responselike@npm:3.0.0" + dependencies: + lowercase-keys: "npm:^3.0.0" + checksum: 8af27153f7e47aa2c07a5f2d538cb1e5872995f0e9ff77def858ecce5c3fe677d42b824a62cde502e56d275ab832b0a8bd350d5cd6b467ac0425214ac12ae658 + languageName: node + linkType: hard + "restore-cursor@npm:^3.1.0": version: 3.1.0 resolution: "restore-cursor@npm:3.1.0" @@ -15713,10 +19169,10 @@ __metadata: languageName: node linkType: hard -"rfdc@npm:^1.3.0": - version: 1.3.0 - resolution: "rfdc@npm:1.3.0" - checksum: a17fd7b81f42c7ae4cb932abd7b2f677b04cc462a03619fb46945ae1ccae17c3bc87c020ffdde1751cbfa8549860a2883486fdcabc9b9de3f3108af32b69a667 +"rfdc@npm:^1.2.0, rfdc@npm:^1.3.0": + version: 1.3.1 + resolution: "rfdc@npm:1.3.1" + checksum: 69f65e3ed30970f8055fac9fbbef9ce578800ca19554eab1dcbffe73a4b8aef536bc4248313889cf25e3b4e38b212c721eabe30856575bf2b2bc3d90f8ba93ef languageName: node linkType: hard @@ -15742,6 +19198,17 @@ __metadata: languageName: node linkType: hard +"rimraf@npm:^5.0.0": + version: 5.0.5 + resolution: "rimraf@npm:5.0.5" + dependencies: + glob: "npm:^10.3.7" + bin: + rimraf: dist/esm/bin.mjs + checksum: d50dbe724f33835decd88395b25ed35995077c60a50ae78ded06e0185418914e555817aad1b4243edbff2254548c2f6ad6f70cc850040bebb4da9e8cc016f586 + languageName: node + linkType: hard + "ripemd160@npm:^2.0.0, ripemd160@npm:^2.0.1": version: 2.0.2 resolution: "ripemd160@npm:2.0.2" @@ -15763,15 +19230,6 @@ __metadata: languageName: node linkType: hard -"run-applescript@npm:^5.0.0": - version: 5.0.0 - resolution: "run-applescript@npm:5.0.0" - dependencies: - execa: "npm:^5.0.0" - checksum: f9977db5770929f3f0db434b8e6aa266498c70dec913c84320c0a06add510cf44e3a048c44da088abee312006f9cbf572fd065cdc8f15d7682afda8755f4114c - languageName: node - linkType: hard - "run-async@npm:^2.4.0": version: 2.4.1 resolution: "run-async@npm:2.4.1" @@ -15798,13 +19256,29 @@ __metadata: linkType: hard "run@npm:^1.4.0": - version: 1.4.0 - resolution: "run@npm:1.4.0" + version: 1.5.0 + resolution: "run@npm:1.5.0" dependencies: minimatch: "npm:*" bin: - runjs: ./cli.js - checksum: 0f4825d86a77f73496a633227cb27e5ba21fda01b1c13541c81f5af8d0ab1c3ad933bb8ce05c6e0c842d7a648f6bfc484cb6b8159249960bb5a8b108397cf198 + runjs: cli.js + checksum: 69907323522292561d3356b2404efe7dd7d4254247ca91399fe8fd6520fbe7a12febd0e9ab2d1cb7e5d19c16df3e3ef28c64bff5934031566a58b5519beb9d0c + languageName: node + linkType: hard + +"rust-verkle-wasm@npm:^0.0.1": + version: 0.0.1 + resolution: "rust-verkle-wasm@npm:0.0.1" + checksum: 07536a7b4d1fe37dcfc9fc19fdee630d26c9c27acd3a18da8daf21c040b87bb162098fd304e1458e4edb72d8ed4cd0e74c9fcd75edb70eb5e29a1a524916ad12 + languageName: node + linkType: hard + +"rustbn-wasm@npm:^0.2.0": + version: 0.2.0 + resolution: "rustbn-wasm@npm:0.2.0" + dependencies: + "@scure/base": "npm:^1.1.1" + checksum: 86729b25a7295f706641366a3ba2bd59a666c1ddbdc40ec4a18f8f8dd5074aaf742ffaf260e80617513954e6a247f4e06f655fe99e9d75fddbdcc4cf0bea32b7 languageName: node linkType: hard @@ -15815,7 +19289,7 @@ __metadata: languageName: node linkType: hard -"rxjs@npm:^6.4.0": +"rxjs@npm:^6.4.0, rxjs@npm:^6.6.6": version: 6.6.7 resolution: "rxjs@npm:6.6.7" dependencies: @@ -15833,15 +19307,15 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.0, safe-array-concat@npm:^1.0.1": - version: 1.0.1 - resolution: "safe-array-concat@npm:1.0.1" +"safe-array-concat@npm:^1.0.0, safe-array-concat@npm:^1.1.0": + version: 1.1.0 + resolution: "safe-array-concat@npm:1.1.0" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.1" + call-bind: "npm:^1.0.5" + get-intrinsic: "npm:^1.2.2" has-symbols: "npm:^1.0.3" isarray: "npm:^2.0.5" - checksum: 4b15ce5fce5ce4d7e744a63592cded88d2f27806ed229eadb2e42629cbcd40e770f7478608e75f455e7fe341acd8c0a01bdcd7146b10645ea7411c5e3c1d1dd8 + checksum: 833d3d950fc7507a60075f9bfaf41ec6dac7c50c7a9d62b1e6b071ecc162185881f92e594ff95c1a18301c881352dd6fd236d56999d5819559db7b92da9c28af languageName: node linkType: hard @@ -15868,14 +19342,14 @@ __metadata: languageName: node linkType: hard -"safe-regex-test@npm:^1.0.0": - version: 1.0.0 - resolution: "safe-regex-test@npm:1.0.0" +"safe-regex-test@npm:^1.0.3": + version: 1.0.3 + resolution: "safe-regex-test@npm:1.0.3" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.1.3" + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" is-regex: "npm:^1.1.4" - checksum: 14a81a7e683f97b2d6e9c8be61fddcf8ed7a02f4e64a825515f96bb1738eb007145359313741d2704d28b55b703a0f6300c749dde7c1dbc13952a2b85048ede2 + checksum: 900bf7c98dc58f08d8523b7012b468e4eb757afa624f198902c0643d7008ba777b0bdc35810ba0b758671ce887617295fb742b3f3968991b178ceca54cb07603 languageName: node linkType: hard @@ -15991,18 +19465,18 @@ __metadata: languageName: node linkType: hard -"semver@npm:7.5.4, semver@npm:^7.2.1, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.5.2, semver@npm:^7.5.4": - version: 7.5.4 - resolution: "semver@npm:7.5.4" +"semver@npm:7.6.0, semver@npm:^7.3.4, semver@npm:^7.3.5, semver@npm:^7.3.7, semver@npm:^7.5.2, semver@npm:^7.5.3, semver@npm:^7.5.4": + version: 7.6.0 + resolution: "semver@npm:7.6.0" dependencies: lru-cache: "npm:^6.0.0" bin: semver: bin/semver.js - checksum: 5160b06975a38b11c1ab55950cb5b8a23db78df88275d3d8a42ccf1f29e55112ac995b3a26a522c36e3b5f76b0445f1eef70d696b8c7862a2b4303d7b0e7609e + checksum: fbfe717094ace0aa8d6332d7ef5ce727259815bd8d8815700853f4faf23aacbd7192522f0dc5af6df52ef4fa85a355ebd2f5d39f554bd028200d6cf481ab9b53 languageName: node linkType: hard -"semver@npm:^6.3.0": +"semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" bin: @@ -16062,6 +19536,17 @@ __metadata: languageName: node linkType: hard +"sentence-case@npm:^3.0.4": + version: 3.0.4 + resolution: "sentence-case@npm:3.0.4" + dependencies: + no-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + upper-case-first: "npm:^2.0.2" + checksum: 9a90527a51300cf5faea7fae0c037728f9ddcff23ac083883774c74d180c0a03c31aab43d5c3347512e8c1b31a0d4712512ec82beb71aa79b85149f9abeb5467 + languageName: node + linkType: hard + "sequelize-pool@npm:^7.1.0": version: 7.1.0 resolution: "sequelize-pool@npm:7.1.0" @@ -16206,26 +19691,29 @@ __metadata: languageName: node linkType: hard -"set-function-length@npm:^1.1.1": - version: 1.1.1 - resolution: "set-function-length@npm:1.1.1" +"set-function-length@npm:^1.2.1": + version: 1.2.1 + resolution: "set-function-length@npm:1.2.1" dependencies: - define-data-property: "npm:^1.1.1" - get-intrinsic: "npm:^1.2.1" + define-data-property: "npm:^1.1.2" + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + get-intrinsic: "npm:^1.2.3" gopd: "npm:^1.0.1" - has-property-descriptors: "npm:^1.0.0" - checksum: a29e255c116c29e3323b851c4f46c58c91be9bb8b065f191e2ea1807cb2c839df56e3175732a498e0c6d54626ba6b6fef896bf699feb7ab70c42dc47eb247c95 + has-property-descriptors: "npm:^1.0.1" + checksum: 1927e296599f2c04d210c1911f1600430a5e49e04a6d8bb03dca5487b95a574da9968813a2ced9a774bd3e188d4a6208352c8f64b8d4674cdb021dca21e190ca languageName: node linkType: hard -"set-function-name@npm:^2.0.0": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" +"set-function-name@npm:^2.0.1": + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" dependencies: - define-data-property: "npm:^1.0.1" + define-data-property: "npm:^1.1.4" + es-errors: "npm:^1.3.0" functions-have-names: "npm:^1.2.3" - has-property-descriptors: "npm:^1.0.0" - checksum: 6be7d3e15be47f4db8a5a563a35c60b5e7c4af91cc900e8972ffad33d3aaa227900faa55f60121cdb04b85866a734bb7fe4cd91f654c632861cc86121a48312a + has-property-descriptors: "npm:^1.0.2" + checksum: fce59f90696c450a8523e754abb305e2b8c73586452619c2bad5f7bf38c7b6b4651895c9db895679c5bef9554339cf3ef1c329b66ece3eda7255785fbe299316 languageName: node linkType: hard @@ -16337,17 +19825,18 @@ __metadata: linkType: hard "side-channel@npm:^1.0.4": - version: 1.0.4 - resolution: "side-channel@npm:1.0.4" + version: 1.0.5 + resolution: "side-channel@npm:1.0.5" dependencies: - call-bind: "npm:^1.0.0" - get-intrinsic: "npm:^1.0.2" - object-inspect: "npm:^1.9.0" - checksum: 054a5d23ee35054b2c4609b9fd2a0587760737782b5d765a9c7852264710cc39c6dcb56a9bbd6c12cd84071648aea3edb2359d2f6e560677eedadce511ac1da5 + call-bind: "npm:^1.0.6" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.4" + object-inspect: "npm:^1.13.1" + checksum: 31312fecb68997ce2893b1f6d1fd07d6dd41e05cc938e82004f056f7de96dd9df599ef9418acdf730dda948e867e933114bd2efe4170c0146d1ed7009700c252 languageName: node linkType: hard -"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3, signal-exit@npm:^3.0.7": +"signal-exit@npm:^3.0.2, signal-exit@npm:^3.0.3": version: 3.0.7 resolution: "signal-exit@npm:3.0.7" checksum: 25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 @@ -16370,6 +19859,13 @@ __metadata: languageName: node linkType: hard +"signedsource@npm:^1.0.0": + version: 1.0.0 + resolution: "signedsource@npm:1.0.0" + checksum: dbb4ade9c94888e83c16d23ef1a43195799de091d366d130be286415e8aeb97b3f25b14fd26fc5888e1335d703ad561374fddee32e43b7cea04751b93d178a47 + languageName: node + linkType: hard + "simple-concat@npm:^1.0.0": version: 1.0.1 resolution: "simple-concat@npm:1.0.1" @@ -16454,6 +19950,32 @@ __metadata: languageName: node linkType: hard +"smartwrap@npm:^2.0.2": + version: 2.0.2 + resolution: "smartwrap@npm:2.0.2" + dependencies: + array.prototype.flat: "npm:^1.2.3" + breakword: "npm:^1.0.5" + grapheme-splitter: "npm:^1.0.4" + strip-ansi: "npm:^6.0.0" + wcwidth: "npm:^1.0.1" + yargs: "npm:^15.1.0" + bin: + smartwrap: src/terminal-adapter.js + checksum: ea104632a832967a04cb739253dbd7d2e194c62bae1c3366d03bb5827870b83842a3e25a7f80287a4b04484ea4f64b51a0657389fc6a6fe701db3b25319ed56f + languageName: node + linkType: hard + +"snake-case@npm:^3.0.4": + version: 3.0.4 + resolution: "snake-case@npm:3.0.4" + dependencies: + dot-case: "npm:^3.0.4" + tslib: "npm:^2.0.3" + checksum: ab19a913969f58f4474fe9f6e8a026c8a2142a01f40b52b79368068343177f818cdfef0b0c6b9558f298782441d5ca8ed5932eb57822439fad791d866e62cecd + languageName: node + linkType: hard + "snapdragon-node@npm:^2.0.1": version: 2.1.1 resolution: "snapdragon-node@npm:2.1.1" @@ -16502,12 +20024,12 @@ __metadata: linkType: hard "socks@npm:^2.7.1": - version: 2.7.1 - resolution: "socks@npm:2.7.1" + version: 2.8.1 + resolution: "socks@npm:2.8.1" dependencies: - ip: "npm:^2.0.0" + ip-address: "npm:^9.0.5" smart-buffer: "npm:^4.2.0" - checksum: 43f69dbc9f34fc8220bc51c6eea1c39715ab3cfdb115d6e3285f6c7d1a603c5c75655668a5bbc11e3c7e2c99d60321fb8d7ab6f38cda6a215fadd0d6d0b52130 + checksum: ac77b515c260473cc7c4452f09b20939e22510ce3ae48385c516d1d5784374d5cc75be3cb18ff66cc985a7f4f2ef8fef84e984c5ec70aad58355ed59241f40a8 languageName: node linkType: hard @@ -16558,26 +20080,68 @@ __metadata: semver: "npm:^5.5.0" tmp: "npm:0.0.33" bin: - solcjs: solcjs - checksum: 7803e011a2a5424e14fc0aa3d7e36eac90130bfe1498eff3298967faee212aa13ca7fb7b98db27de449f086fbf92e87c24483e84ea5faa6a50cbe24e2961d002 + solcjs: solcjs + checksum: 7803e011a2a5424e14fc0aa3d7e36eac90130bfe1498eff3298967faee212aa13ca7fb7b98db27de449f086fbf92e87c24483e84ea5faa6a50cbe24e2961d002 + languageName: node + linkType: hard + +"solhint-community@npm:^3.7.0": + version: 3.7.0 + resolution: "solhint-community@npm:3.7.0" + dependencies: + "@solidity-parser/parser": "npm:^0.16.0" + ajv: "npm:^6.12.6" + antlr4: "npm:^4.11.0" + ast-parents: "npm:^0.0.1" + chalk: "npm:^4.1.2" + commander: "npm:^11.1.0" + cosmiconfig: "npm:^8.0.0" + fast-diff: "npm:^1.2.0" + glob: "npm:^8.0.3" + ignore: "npm:^5.2.4" + js-yaml: "npm:^4.1.0" + lodash: "npm:^4.17.21" + pluralize: "npm:^8.0.0" + prettier: "npm:^2.8.3" + semver: "npm:^6.3.0" + strip-ansi: "npm:^6.0.1" + table: "npm:^6.8.1" + text-table: "npm:^0.2.0" + dependenciesMeta: + prettier: + optional: true + bin: + solhint: solhint.js + checksum: 05b7ac7ce7fb978c3196400b00fddd361de8503cdc2d7be83b858775c6fe9b3f67a93b6d791f1f182f80759874926849351a6ef71f214ceef42211f5eb9336b1 languageName: node linkType: hard -"solhint-plugin-prettier@npm:^0.0.5": - version: 0.0.5 - resolution: "solhint-plugin-prettier@npm:0.0.5" +"solhint-graph-config@workspace:^0.0.1, solhint-graph-config@workspace:packages/solhint-graph-config": + version: 0.0.0-use.local + resolution: "solhint-graph-config@workspace:packages/solhint-graph-config" + peerDependencies: + prettier: ^3.2.5 + prettier-plugin-solidity: ^1.3.1 + solhint: ^4.1.1 + languageName: unknown + linkType: soft + +"solhint-plugin-prettier@npm:^0.1.0": + version: 0.1.0 + resolution: "solhint-plugin-prettier@npm:0.1.0" dependencies: + "@prettier/sync": "npm:^0.3.0" prettier-linter-helpers: "npm:^1.0.0" peerDependencies: - prettier: ^1.15.0 || ^2.0.0 - prettier-plugin-solidity: ^1.0.0-alpha.14 - checksum: 3dd40c9e7d7c0cf9a36816cb185f75ea12b51b976e13568ab3d4e914c3160d75b6b8fe5b18bf33c06e4a17f7dcc9d25a22dfe1f3fb9a27c4911e6d41234ef5e2 + prettier: ^3.0.0 + prettier-plugin-solidity: ^1.0.0 + checksum: 4f6211ddd954c2ffd82a2766dc4453f3036fd7022aea5a54f63b00c4afcd4669c42ef6add8e255d43ed8c0c592917f338dd34b66bc7c017bbfd3eb133952529d languageName: node linkType: hard -"solhint@npm:^3.3.6": - version: 3.6.2 - resolution: "solhint@npm:3.6.2" +"solhint@npm:^4.1.1": + version: 4.1.1 + resolution: "solhint@npm:4.1.1" dependencies: "@solidity-parser/parser": "npm:^0.16.0" ajv: "npm:^6.12.6" @@ -16590,6 +20154,7 @@ __metadata: glob: "npm:^8.0.3" ignore: "npm:^5.2.4" js-yaml: "npm:^4.1.0" + latest-version: "npm:^7.0.0" lodash: "npm:^4.17.21" pluralize: "npm:^8.0.0" prettier: "npm:^2.8.3" @@ -16602,7 +20167,7 @@ __metadata: optional: true bin: solhint: solhint.js - checksum: db250dc141e92ca33a9adee11b01232dfa3883f053d781f30cd471c22af6d551e8b9ff839b7f1abbe9c0618204b0891b63fa3814ae049d824f98a4c5bb32b42b + checksum: b4bdb21bdc13f7ba3436d571a30cae6cb8dfb58ab1387df8bef25eeca25c8fbb3f625c49a5dddea41f8361aaeb4d8e2e9f986f580663ddd4574fd3d5de5f66c9 languageName: node linkType: hard @@ -16615,10 +20180,10 @@ __metadata: languageName: node linkType: hard -"solidity-comments-extractor@npm:^0.0.7": - version: 0.0.7 - resolution: "solidity-comments-extractor@npm:0.0.7" - checksum: 57fb166ff71812404288ae1a386bb9bbb6330662aedc3b45d89f6f0ce51ee0e36c9f4b9d4fd363c2b37fbf607e42df088e734c532fb93e2f345601b429813d9e +"solidity-comments-extractor@npm:^0.0.8": + version: 0.0.8 + resolution: "solidity-comments-extractor@npm:0.0.8" + checksum: 86e56bdfc90b3af3a5e244a2b5e215db78b12b6045d68699ecb2304326edb906c1b083c0e1a074cde77e9e8cdeb978ae5ef8666d821bef83db89c2708a8b6192 languageName: node linkType: hard @@ -16731,6 +20296,16 @@ __metadata: languageName: node linkType: hard +"spawndamnit@npm:^2.0.0": + version: 2.0.0 + resolution: "spawndamnit@npm:2.0.0" + dependencies: + cross-spawn: "npm:^5.1.0" + signal-exit: "npm:^3.0.2" + checksum: 3d3aa1b750130a78cad591828c203e706cb132fbd7dccab8ae5354984117cd1464c7f9ef6c4756e6590fec16bab77fe2c85d1eb8e59006d303836007922d359c + languageName: node + linkType: hard + "spdx-correct@npm:^3.0.0": version: 3.2.0 resolution: "spdx-correct@npm:3.2.0" @@ -16742,9 +20317,9 @@ __metadata: linkType: hard "spdx-exceptions@npm:^2.1.0": - version: 2.3.0 - resolution: "spdx-exceptions@npm:2.3.0" - checksum: 83089e77d2a91cb6805a5c910a2bedb9e50799da091f532c2ba4150efdef6e53f121523d3e2dc2573a340dc0189e648b03157097f65465b3a0c06da1f18d7e8a + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: 37217b7762ee0ea0d8b7d0c29fd48b7e4dfb94096b109d6255b589c561f57da93bf4e328c0290046115961b9209a8051ad9f525e48d433082fc79f496a4ea940 languageName: node linkType: hard @@ -16759,9 +20334,9 @@ __metadata: linkType: hard "spdx-license-ids@npm:^3.0.0": - version: 3.0.16 - resolution: "spdx-license-ids@npm:3.0.16" - checksum: 7d88b8f01308948bb3ea69c066448f2776cf3d35a410d19afb836743086ced1566f6824ee8e6d67f8f25aa81fa86d8076a666c60ac4528caecd55e93edb5114e + version: 3.0.17 + resolution: "spdx-license-ids@npm:3.0.17" + checksum: ddf9477b5afc70f1a7d3bf91f0b8e8a1c1b0fa65d2d9a8b5c991b1a2ba91b693d8b9749700119d5ce7f3fbf307ac421087ff43d321db472605e98a5804f80eac languageName: node linkType: hard @@ -16790,6 +20365,22 @@ __metadata: languageName: node linkType: hard +"sponge-case@npm:^1.0.1": + version: 1.0.1 + resolution: "sponge-case@npm:1.0.1" + dependencies: + tslib: "npm:^2.0.3" + checksum: dbe42f300ae9f7fbd83c40f71c2a61ecf9c86b927b5668bae067d1e516e314671cc85166f87017e51b56938409b1fc042719eb46a6d5bb30cc1cf23252a82761 + languageName: node + linkType: hard + +"sprintf-js@npm:^1.1.3": + version: 1.1.3 + resolution: "sprintf-js@npm:1.1.3" + checksum: 09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec + languageName: node + linkType: hard + "sprintf-js@npm:~1.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -16875,9 +20466,9 @@ __metadata: linkType: hard "stream-shift@npm:^1.0.0": - version: 1.0.1 - resolution: "stream-shift@npm:1.0.1" - checksum: b63a0d178cde34b920ad93e2c0c9395b840f408d36803b07c61416edac80ef9e480a51910e0ceea0d679cec90921bcd2cccab020d3a9fa6c73a98b0fbec132fd + version: 1.0.3 + resolution: "stream-shift@npm:1.0.3" + checksum: 939cd1051ca750d240a0625b106a2b988c45fb5a3be0cebe9a9858cb01bc1955e8c7b9fac17a9462976bea4a7b704e317c5c2200c70f0ca715a3363b9aa4fd3b languageName: node linkType: hard @@ -16900,6 +20491,22 @@ __metadata: languageName: node linkType: hard +"stream-transform@npm:^2.1.3": + version: 2.1.3 + resolution: "stream-transform@npm:2.1.3" + dependencies: + mixme: "npm:^0.5.1" + checksum: 8a4b40e1ee952869358c12bbb3da3aa9ca30c8964f8f8eef2058a3b6b2202d7a856657ef458a5f2402a464310d177f92d2e4a119667854fce4b17c05e3c180bd + languageName: node + linkType: hard + +"streamsearch@npm:^1.1.0": + version: 1.1.0 + resolution: "streamsearch@npm:1.1.0" + checksum: fbd9aecc2621364384d157f7e59426f4bfd385e8b424b5aaa79c83a6f5a1c8fd2e4e3289e95de1eb3511cb96bb333d6281a9919fafce760e4edb35b2cd2facab + languageName: node + linkType: hard + "strict-uri-encode@npm:^1.0.0": version: 1.1.0 resolution: "strict-uri-encode@npm:1.1.0" @@ -16914,7 +20521,7 @@ __metadata: languageName: node linkType: hard -"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.3": +"string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.0.0, string-width@npm:^4.1.0, string-width@npm:^4.2.0, string-width@npm:^4.2.2, string-width@npm:^4.2.3": version: 4.2.3 resolution: "string-width@npm:4.2.3" dependencies: @@ -17080,6 +20687,13 @@ __metadata: languageName: node linkType: hard +"strip-bom@npm:^3.0.0": + version: 3.0.0 + resolution: "strip-bom@npm:3.0.0" + checksum: 51201f50e021ef16672593d7434ca239441b7b760e905d9f33df6e4f3954ff54ec0e0a06f100d028af0982d6f25c35cd5cda2ce34eaebccd0250b8befb90d8f1 + languageName: node + linkType: hard + "strip-final-newline@npm:^2.0.0": version: 2.0.0 resolution: "strip-final-newline@npm:2.0.0" @@ -17087,13 +20701,6 @@ __metadata: languageName: node linkType: hard -"strip-final-newline@npm:^3.0.0": - version: 3.0.0 - resolution: "strip-final-newline@npm:3.0.0" - checksum: a771a17901427bac6293fd416db7577e2bc1c34a19d38351e9d5478c3c415f523f391003b42ed475f27e33a78233035df183525395f731d3bfb8cdcbd4da08ce - languageName: node - linkType: hard - "strip-hex-prefix@npm:1.0.0": version: 1.0.0 resolution: "strip-hex-prefix@npm:1.0.0" @@ -17112,13 +20719,20 @@ __metadata: languageName: node linkType: hard -"strip-json-comments@npm:3.1.1, strip-json-comments@npm:^3.1.0, strip-json-comments@npm:^3.1.1": +"strip-json-comments@npm:3.1.1, strip-json-comments@npm:^3.1.1": version: 3.1.1 resolution: "strip-json-comments@npm:3.1.1" checksum: 9681a6257b925a7fa0f285851c0e613cc934a50661fa7bb41ca9cbbff89686bb4a0ee366e6ecedc4daafd01e83eee0720111ab294366fe7c185e935475ebcecd languageName: node linkType: hard +"strip-json-comments@npm:~2.0.1": + version: 2.0.1 + resolution: "strip-json-comments@npm:2.0.1" + checksum: b509231cbdee45064ff4f9fd73609e2bcc4e84a4d508e9dd0f31f70356473fde18abfb5838c17d56fb236f5a06b102ef115438de0600b749e818a35fbbc48c43 + languageName: node + linkType: hard + "supports-color@npm:8.1.1": version: 8.1.1 resolution: "supports-color@npm:8.1.1" @@ -17169,6 +20783,15 @@ __metadata: languageName: node linkType: hard +"swap-case@npm:^2.0.2": + version: 2.0.2 + resolution: "swap-case@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 6a47c1926e06395ead750905e103be388aeec8c9697f20b14bc3e1e86fcb4fc78e5033197afe6cc8bbed80f0a4ee1f184b0fa22eec7f4a767bdfd278683d52eb + languageName: node + linkType: hard + "swarm-js@npm:^0.1.40": version: 0.1.42 resolution: "swarm-js@npm:0.1.42" @@ -17208,17 +20831,17 @@ __metadata: languageName: node linkType: hard -"synckit@npm:^0.8.5": - version: 0.8.5 - resolution: "synckit@npm:0.8.5" +"synckit@npm:^0.8.6": + version: 0.8.8 + resolution: "synckit@npm:0.8.8" dependencies: - "@pkgr/utils": "npm:^2.3.1" - tslib: "npm:^2.5.0" - checksum: 9827f828cabc404b3a147c38f824c8d5b846eb6f65189d965aa0b71ea8ecda5048f8f50b4bdfd8813148844175233cff56c6bc8d87a7118cf10707df870519f4 + "@pkgr/core": "npm:^0.1.0" + tslib: "npm:^2.6.2" + checksum: c3d3aa8e284f3f84f2f868b960c9f49239b364e35f6d20825a448449a3e9c8f49fe36cdd5196b30615682f007830d46f2ea354003954c7336723cb821e4b6519 languageName: node linkType: hard -"table@npm:^6.0.9, table@npm:^6.8.0, table@npm:^6.8.1": +"table@npm:^6.8.0, table@npm:^6.8.1": version: 6.8.1 resolution: "table@npm:6.8.1" dependencies: @@ -17295,6 +20918,13 @@ __metadata: languageName: node linkType: hard +"term-size@npm:^2.1.0": + version: 2.2.1 + resolution: "term-size@npm:2.2.1" + checksum: 89f6bba1d05d425156c0910982f9344d9e4aebf12d64bfa1f460d93c24baa7bc4c4a21d355fbd7153c316433df0538f64d0ae6e336cc4a69fdda4f85d62bc79d + languageName: node + linkType: hard + "test-value@npm:^2.1.0": version: 2.1.0 resolution: "test-value@npm:2.1.0" @@ -17413,10 +21043,19 @@ __metadata: languageName: node linkType: hard -"titleize@npm:^3.0.0": - version: 3.0.0 - resolution: "titleize@npm:3.0.0" - checksum: 5ae6084ba299b5782f95e3fe85ea9f0fa4d74b8ae722b6b3208157e975589fbb27733aeba4e5080fa9314a856044ef52caa61b87caea4b1baade951a55c06336 +"tiny-lru@npm:^8.0.2": + version: 8.0.2 + resolution: "tiny-lru@npm:8.0.2" + checksum: 32dc73db748ae50bf43498f81150ed23922c924d7a3665ea240c7041abbbd5e8667c05328fd520ca923b4d10b89e69a4ba671365eaac221c6f7eb8b898530506 + languageName: node + linkType: hard + +"title-case@npm:^3.0.3": + version: 3.0.3 + resolution: "title-case@npm:3.0.3" + dependencies: + tslib: "npm:^2.0.3" + checksum: face56f686060f777b43a180d371407124d201eb4238c19d9e97030fd54859696ca4e2ca499cc232f8700f24f2414cc08aab9fdf6d39acff055dd825a4d86d6a languageName: node linkType: hard @@ -17445,6 +21084,13 @@ __metadata: languageName: node linkType: hard +"to-fast-properties@npm:^2.0.0": + version: 2.0.0 + resolution: "to-fast-properties@npm:2.0.0" + checksum: b214d21dbfb4bce3452b6244b336806ffea9c05297148d32ebb428d5c43ce7545bdfc65a1ceb58c9ef4376a65c0cb2854d645f33961658b3e3b4f84910ddcdd7 + languageName: node + linkType: hard + "to-object-path@npm:^0.3.0": version: 0.3.0 resolution: "to-object-path@npm:0.3.0" @@ -17544,12 +21190,19 @@ __metadata: languageName: node linkType: hard +"ts-algebra@npm:^1.2.2": + version: 1.2.2 + resolution: "ts-algebra@npm:1.2.2" + checksum: dabfb7fad18b3bb56ed6b14404c2d9d7d41f181df599d50ad6643c6ff1afc459524969d80898183f9e5c66378163799991bfac799790899034ae8cfc99904c74 + languageName: node + linkType: hard + "ts-api-utils@npm:^1.0.1": - version: 1.0.3 - resolution: "ts-api-utils@npm:1.0.3" + version: 1.2.1 + resolution: "ts-api-utils@npm:1.2.1" peerDependencies: typescript: ">=4.2.0" - checksum: 9408338819c3aca2a709f0bc54e3f874227901506cacb1163612a6c8a43df224174feb965a5eafdae16f66fc68fd7bfee8d3275d0fa73fbb8699e03ed26520c9 + checksum: 8ddb493e7ae581d3f57a2e469142feb60b420d4ad8366ab969fe8e36531f8f301f370676b47e8d97f28b5f5fd10d6f2d55f656943a8546ef95e35ce5cf117754 languageName: node linkType: hard @@ -17598,8 +21251,8 @@ __metadata: linkType: hard "ts-node@npm:^10.9.1": - version: 10.9.1 - resolution: "ts-node@npm:10.9.1" + version: 10.9.2 + resolution: "ts-node@npm:10.9.2" dependencies: "@cspotcode/source-map-support": "npm:^0.8.0" "@tsconfig/node10": "npm:^1.0.7" @@ -17631,24 +21284,49 @@ __metadata: ts-node-script: dist/bin-script.js ts-node-transpile-only: dist/bin-transpile.js ts-script: dist/bin-script-deprecated.js - checksum: 95187932fb83f3901e22546bd2feeac7d2feb4f412f42ac3a595f049a23e8dcf70516dffb51866391228ea2dbcfaea039e250fb2bb334d48a86ab2b6aea0ae2d + checksum: 5f29938489f96982a25ba650b64218e83a3357d76f7bede80195c65ab44ad279c8357264639b7abdd5d7e75fc269a83daa0e9c62fd8637a3def67254ecc9ddc2 + languageName: node + linkType: hard + +"tsconfig-paths@npm:^4.2.0": + version: 4.2.0 + resolution: "tsconfig-paths@npm:4.2.0" + dependencies: + json5: "npm:^2.2.2" + minimist: "npm:^1.2.6" + strip-bom: "npm:^3.0.0" + checksum: 09a5877402d082bb1134930c10249edeebc0211f36150c35e1c542e5b91f1047b1ccf7da1e59babca1ef1f014c525510f4f870de7c9bda470c73bb4e2721b3ea languageName: node linkType: hard -"tslib@npm:^1.11.1, tslib@npm:^1.8.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": +"tslib@npm:^1.11.1, tslib@npm:^1.9.0, tslib@npm:^1.9.3": version: 1.14.1 resolution: "tslib@npm:1.14.1" checksum: 69ae09c49eea644bc5ebe1bca4fa4cc2c82b7b3e02f43b84bd891504edf66dbc6b2ec0eef31a957042de2269139e4acff911e6d186a258fb14069cd7f6febce2 languageName: node linkType: hard -"tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.0": +"tslib@npm:^2.0.0, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.1, tslib@npm:^2.4.0, tslib@npm:^2.5.0, tslib@npm:^2.6.1, tslib@npm:^2.6.2": version: 2.6.2 resolution: "tslib@npm:2.6.2" checksum: e03a8a4271152c8b26604ed45535954c0a45296e32445b4b87f8a5abdb2421f40b59b4ca437c4346af0f28179780d604094eb64546bee2019d903d01c6c19bdb languageName: node linkType: hard +"tslib@npm:~2.4.0": + version: 2.4.1 + resolution: "tslib@npm:2.4.1" + checksum: 9ac0e4fd1033861f0b4f0d848dc3009ebcc3aa4757a06e8602a2d8a7aed252810e3540e54e70709f06c0f95311faa8584f769bcbede48aff785eb7e4d399b9ec + languageName: node + linkType: hard + +"tslib@npm:~2.5.0": + version: 2.5.3 + resolution: "tslib@npm:2.5.3" + checksum: 4cb1817d34fae5b27d146e6c4a468d4155097d95c1335d0bc9690f11f33e63844806bf4ed6d97c30c72b8d85261b66cbbe16d871d9c594ac05701ec83e62a607 + languageName: node + linkType: hard + "tsort@npm:0.0.1": version: 0.0.1 resolution: "tsort@npm:0.0.1" @@ -17656,14 +21334,20 @@ __metadata: languageName: node linkType: hard -"tsutils@npm:^3.21.0": - version: 3.21.0 - resolution: "tsutils@npm:3.21.0" +"tty-table@npm:^4.1.5": + version: 4.2.3 + resolution: "tty-table@npm:4.2.3" dependencies: - tslib: "npm:^1.8.1" - peerDependencies: - typescript: ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - checksum: 02f19e458ec78ead8fffbf711f834ad8ecd2cc6ade4ec0320790713dccc0a412b99e7fd907c4cda2a1dc602c75db6f12e0108e87a5afad4b2f9e90a24cabd5a2 + chalk: "npm:^4.1.2" + csv: "npm:^5.5.3" + kleur: "npm:^4.1.5" + smartwrap: "npm:^2.0.2" + strip-ansi: "npm:^6.0.1" + wcwidth: "npm:^1.0.1" + yargs: "npm:^17.7.1" + bin: + tty-table: adapters/terminal-adapter.js + checksum: 408b75693a2b0bae8cd27940c42d9cd29539deb01d90314e708f34f49c80697a3bf55bf5573f02a8aa6dc3ddee78b9e1bcf9ae986d1ec77896ae1d0bd5efb071 languageName: node linkType: hard @@ -17722,6 +21406,13 @@ __metadata: languageName: node linkType: hard +"type-fest@npm:^0.13.1": + version: 0.13.1 + resolution: "type-fest@npm:0.13.1" + checksum: 0c0fa07ae53d4e776cf4dac30d25ad799443e9eef9226f9fddbb69242db86b08584084a99885cfa5a9dfe4c063ebdc9aa7b69da348e735baede8d43f1aeae93b + languageName: node + linkType: hard + "type-fest@npm:^0.18.0": version: 0.18.1 resolution: "type-fest@npm:0.18.1" @@ -17827,50 +21518,55 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-buffer@npm:1.0.0" +"typed-array-buffer@npm:^1.0.1": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" dependencies: - call-bind: "npm:^1.0.2" - get-intrinsic: "npm:^1.2.1" - is-typed-array: "npm:^1.1.10" - checksum: ebad66cdf00c96b1395dffc7873169cf09801fca5954507a484f41f253feb1388d815db297b0b3bb8ce7421eac6f7ff45e2ec68450a3d68408aa4ae02fcf3a6c + call-bind: "npm:^1.0.7" + es-errors: "npm:^1.3.0" + is-typed-array: "npm:^1.1.13" + checksum: 9e043eb38e1b4df4ddf9dde1aa64919ae8bb909571c1cc4490ba777d55d23a0c74c7d73afcdd29ec98616d91bb3ae0f705fad4421ea147e1daf9528200b562da languageName: node linkType: hard "typed-array-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-length@npm:1.0.0" + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" dependencies: - call-bind: "npm:^1.0.2" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" - has-proto: "npm:^1.0.1" - is-typed-array: "npm:^1.1.10" - checksum: 6696435d53ce0e704ff6760c57ccc35138aec5f87859e03eb2a3246336d546feae367952dbc918116f3f0dffbe669734e3cbd8960283c2fa79aac925db50d888 + gopd: "npm:^1.0.1" + has-proto: "npm:^1.0.3" + is-typed-array: "npm:^1.1.13" + checksum: fcebeffb2436c9f355e91bd19e2368273b88c11d1acc0948a2a306792f1ab672bce4cfe524ab9f51a0505c9d7cd1c98eff4235c4f6bfef6a198f6cfc4ff3d4f3 languageName: node linkType: hard "typed-array-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-offset@npm:1.0.0" + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.2" + available-typed-arrays: "npm:^1.0.7" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" - has-proto: "npm:^1.0.1" - is-typed-array: "npm:^1.1.10" - checksum: 4036ce007ae9752931bed3dd61e0d6de2a3e5f6a5a85a05f3adb35388d2c0728f9b1a1e638d75579f168e49c289bfb5417f00e96d4ab081f38b647fc854ff7a5 + gopd: "npm:^1.0.1" + has-proto: "npm:^1.0.3" + is-typed-array: "npm:^1.1.13" + checksum: d2628bc739732072e39269389a758025f75339de2ed40c4f91357023c5512d237f255b633e3106c461ced41907c1bf9a533c7e8578066b0163690ca8bc61b22f languageName: node linkType: hard "typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" + version: 1.0.5 + resolution: "typed-array-length@npm:1.0.5" dependencies: - call-bind: "npm:^1.0.2" + call-bind: "npm:^1.0.7" for-each: "npm:^0.3.3" - is-typed-array: "npm:^1.1.9" - checksum: c5163c0103d07fefc8a2ad0fc151f9ca9a1f6422098c00f695d55f9896e4d63614cd62cf8d8a031c6cee5f418e8980a533796597174da4edff075b3d275a7e23 + gopd: "npm:^1.0.1" + has-proto: "npm:^1.0.3" + is-typed-array: "npm:^1.1.13" + possible-typed-array-names: "npm:^1.0.0" + checksum: 5cc0f79196e70a92f8f40846cfa62b3de6be51e83f73655e137116cf65e3c29a288502b18cc8faf33c943c2470a4569009e1d6da338441649a2db2f135761ad5 languageName: node linkType: hard @@ -17890,7 +21586,22 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.7.4": +"typescript-eslint@npm:^7.0.2": + version: 7.0.2 + resolution: "typescript-eslint@npm:7.0.2" + dependencies: + "@typescript-eslint/eslint-plugin": "npm:7.0.2" + "@typescript-eslint/parser": "npm:7.0.2" + peerDependencies: + eslint: ^8.56.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 947216bccdb392c1e5f1228772185afbe306db305f1f61343d3cb315aa6c80a928709172498af62536b50c1e7c91e263eed7886bb4b328ca8850ffb1ea71a3d9 + languageName: node + linkType: hard + +"typescript@npm:^4.0.2, typescript@npm:^4.7.4": version: 4.9.5 resolution: "typescript@npm:4.9.5" bin: @@ -17900,17 +21611,17 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^5.1.6": - version: 5.3.2 - resolution: "typescript@npm:5.3.2" +"typescript@npm:^5.0.4, typescript@npm:^5.1.6, typescript@npm:^5.3.3": + version: 5.3.3 + resolution: "typescript@npm:5.3.3" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: d7dbe1fbe19039e36a65468ea64b5d338c976550394ba576b7af9c68ed40c0bc5d12ecce390e4b94b287a09a71bd3229f19c2d5680611f35b7c53a3898791159 + checksum: e33cef99d82573624fc0f854a2980322714986bc35b9cb4d1ce736ed182aeab78e2cb32b385efa493b2a976ef52c53e20d6c6918312353a91850e2b76f1ea44f languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^4.7.4#optional!builtin": +"typescript@patch:typescript@npm%3A^4.0.2#optional!builtin, typescript@patch:typescript@npm%3A^4.7.4#optional!builtin": version: 4.9.5 resolution: "typescript@patch:typescript@npm%3A4.9.5#optional!builtin::version=4.9.5&hash=289587" bin: @@ -17920,13 +21631,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@npm%3A^5.1.6#optional!builtin": - version: 5.3.2 - resolution: "typescript@patch:typescript@npm%3A5.3.2#optional!builtin::version=5.3.2&hash=e012d7" +"typescript@patch:typescript@npm%3A^5.0.4#optional!builtin, typescript@patch:typescript@npm%3A^5.1.6#optional!builtin, typescript@patch:typescript@npm%3A^5.3.3#optional!builtin": + version: 5.3.3 + resolution: "typescript@patch:typescript@npm%3A5.3.3#optional!builtin::version=5.3.3&hash=e012d7" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 73c8bad74e732d93211c9d77f28b03307e2f5fc6a0afc73f4b783261ab567686a16d6ae958bdaef383a00be1b0b8c8b6741dd6ca3d13af4963fa7e47456d49c7 + checksum: 1d0a5f4ce496c42caa9a30e659c467c5686eae15d54b027ee7866744952547f1be1262f2d40de911618c242b510029d51d43ff605dba8fb740ec85ca2d3f9500 languageName: node linkType: hard @@ -17960,6 +21671,13 @@ __metadata: languageName: node linkType: hard +"ua-parser-js@npm:^1.0.35": + version: 1.0.37 + resolution: "ua-parser-js@npm:1.0.37" + checksum: dac8cf82a55b2e097bd2286954e01454c4cfcf23c9d9b56961ce94bda3cec5a38ca536e6e84c20a4000a9d4b4a4abcbd98ec634ccebe21be36595ea3069126e4 + languageName: node + linkType: hard + "uglify-js@npm:^3.1.4": version: 3.17.4 resolution: "uglify-js@npm:3.17.4" @@ -18016,6 +21734,13 @@ __metadata: languageName: node linkType: hard +"unc-path-regex@npm:^0.1.2": + version: 0.1.2 + resolution: "unc-path-regex@npm:0.1.2" + checksum: bf9c781c4e2f38e6613ea17a51072e4b416840fbe6eeb244597ce9b028fac2fb6cfd3dde1f14111b02c245e665dc461aab8168ecc30b14364d02caa37f812996 + languageName: node + linkType: hard + "underscore@npm:1.9.1": version: 1.9.1 resolution: "underscore@npm:1.9.1" @@ -18038,11 +21763,11 @@ __metadata: linkType: hard "undici@npm:^5.14.0": - version: 5.28.1 - resolution: "undici@npm:5.28.1" + version: 5.28.3 + resolution: "undici@npm:5.28.3" dependencies: "@fastify/busboy": "npm:^2.0.0" - checksum: d7421957f829cb1e8188d1e136454cb0ab30a275213c9831bcbaec5aa15191fe8b094472d7d0d35f62a0cc50aba430ec7193d1e87ded01616a24ef8f673d42f0 + checksum: 3c559ae50ef3104b7085251445dda6f4de871553b9e290845649d2f80b06c0c9cfcdf741b0029c6b20d36c82e6a74dc815b139fa9a26757d70728074ca6d6f5c languageName: node linkType: hard @@ -18097,6 +21822,15 @@ __metadata: languageName: node linkType: hard +"unixify@npm:^1.0.0": + version: 1.0.0 + resolution: "unixify@npm:1.0.0" + dependencies: + normalize-path: "npm:^2.1.1" + checksum: 8b89100619ebde9f0ab4024a4d402316fb7b1d4853723410fc828944e8d3d01480f210cddf94d9a1699559f8180d861eb6323da8011b7bcc1bbaf6a11a5b1f1e + languageName: node + linkType: hard + "unorm@npm:^1.3.3": version: 1.6.0 resolution: "unorm@npm:1.6.0" @@ -18121,10 +21855,35 @@ __metadata: languageName: node linkType: hard -"untildify@npm:^4.0.0": - version: 4.0.0 - resolution: "untildify@npm:4.0.0" - checksum: d758e624c707d49f76f7511d75d09a8eda7f2020d231ec52b67ff4896bcf7013be3f9522d8375f57e586e9a2e827f5641c7e06ee46ab9c435fc2b2b2e9de517a +"update-browserslist-db@npm:^1.0.13": + version: 1.0.13 + resolution: "update-browserslist-db@npm:1.0.13" + dependencies: + escalade: "npm:^3.1.1" + picocolors: "npm:^1.0.0" + peerDependencies: + browserslist: ">= 4.21.0" + bin: + update-browserslist-db: cli.js + checksum: e52b8b521c78ce1e0c775f356cd16a9c22c70d25f3e01180839c407a5dc787fb05a13f67560cbaf316770d26fa99f78f1acd711b1b54a4f35d4820d4ea7136e6 + languageName: node + linkType: hard + +"upper-case-first@npm:^2.0.2": + version: 2.0.2 + resolution: "upper-case-first@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: ccad6a0b143310ebfba2b5841f30bef71246297385f1329c022c902b2b5fc5aee009faf1ac9da5ab3ba7f615b88f5dc1cd80461b18a8f38cb1d4c3eb92538ea9 + languageName: node + linkType: hard + +"upper-case@npm:^2.0.2": + version: 2.0.2 + resolution: "upper-case@npm:2.0.2" + dependencies: + tslib: "npm:^2.0.3" + checksum: 5ac176c9d3757abb71400df167f9abb46d63152d5797c630d1a9f083fbabd89711fb4b3dc6de06ff0138fe8946fa5b8518b4fcdae9ca8a3e341417075beae069 languageName: node linkType: hard @@ -18170,6 +21929,13 @@ __metadata: languageName: node linkType: hard +"urlpattern-polyfill@npm:^8.0.0": + version: 8.0.2 + resolution: "urlpattern-polyfill@npm:8.0.2" + checksum: 5388bbe8459dbd8861ee7cb97904be915dd863a9789c2191c528056f16adad7836ec22762ed002fed44e8995d0f98bdfb75a606466b77233e70d0f61b969aaf9 + languageName: node + linkType: hard + "use@npm:^3.1.0": version: 3.1.1 resolution: "use@npm:3.1.1" @@ -18286,13 +22052,6 @@ __metadata: languageName: node linkType: hard -"v8-compile-cache@npm:^2.0.3": - version: 2.4.0 - resolution: "v8-compile-cache@npm:2.4.0" - checksum: 387851192545e7f4d691ba674de90890bba76c0f08ee4909ab862377f556221e75b3a361466490e201203401d64d7795f889882bdabc98b6f3c0bf1038a535be - languageName: node - linkType: hard - "validate-npm-package-license@npm:^3.0.1": version: 3.0.4 resolution: "validate-npm-package-license@npm:3.0.4" @@ -18310,6 +22069,13 @@ __metadata: languageName: node linkType: hard +"value-or-promise@npm:1.0.12, value-or-promise@npm:^1.0.11, value-or-promise@npm:^1.0.12": + version: 1.0.12 + resolution: "value-or-promise@npm:1.0.12" + checksum: b75657b74e4d17552bd88e0c2857020fbab34a4d091dc058db18c470e7da0336067e72c130b3358e3321ac0a6ff11c0b92b67a382318a3705ad5d57de7ff3262 + languageName: node + linkType: hard + "varint@npm:^5.0.0, varint@npm:^5.0.2, varint@npm:~5.0.0": version: 5.0.2 resolution: "varint@npm:5.0.2" @@ -18364,6 +22130,13 @@ __metadata: languageName: node linkType: hard +"web-streams-polyfill@npm:^3.2.1": + version: 3.3.3 + resolution: "web-streams-polyfill@npm:3.3.3" + checksum: 64e855c47f6c8330b5436147db1c75cb7e7474d924166800e8e2aab5eb6c76aac4981a84261dd2982b3e754490900b99791c80ae1407a9fa0dcff74f82ea3a7f + languageName: node + linkType: hard + "web3-bzz@npm:1.10.0": version: 1.10.0 resolution: "web3-bzz@npm:1.10.0" @@ -19170,8 +22943,8 @@ __metadata: linkType: hard "web3-utils@npm:^1.0.0-beta.31, web3-utils@npm:^1.3.0": - version: 1.10.3 - resolution: "web3-utils@npm:1.10.3" + version: 1.10.4 + resolution: "web3-utils@npm:1.10.4" dependencies: "@ethereumjs/util": "npm:^8.1.0" bn.js: "npm:^5.2.1" @@ -19181,7 +22954,7 @@ __metadata: number-to-bn: "npm:1.7.0" randombytes: "npm:^2.1.0" utf8: "npm:3.0.0" - checksum: c0c3ed4c46f4d8faa30410035e65e5041607c1d4ce20e1218b9abee471309510cf5efe0de371c4a812f5a4de6aea7bd3129e55402a7728fe98ae770c10e8b20f + checksum: fbd5c8ec71e944e9e66e3436dbd4446927c3edc95f81928723f9ac137e0d821c5cbb92dba0ed5bbac766f919f919c9d8e316e459c51d876d5188321642676677 languageName: node linkType: hard @@ -19230,6 +23003,19 @@ __metadata: languageName: node linkType: hard +"webcrypto-core@npm:^1.7.8": + version: 1.7.8 + resolution: "webcrypto-core@npm:1.7.8" + dependencies: + "@peculiar/asn1-schema": "npm:^2.3.8" + "@peculiar/json-schema": "npm:^1.1.12" + asn1js: "npm:^3.0.1" + pvtsutils: "npm:^1.3.5" + tslib: "npm:^2.6.2" + checksum: 4c6ef9ae4ae27489f88b7c571494b058120178528f25efe87b97cbc64ead03a6468a614f6269927d13735e4f5ce1d1f7599cf4385ee9b61a13921964a5748a66 + languageName: node + linkType: hard + "webidl-conversions@npm:^3.0.0": version: 3.0.1 resolution: "webidl-conversions@npm:3.0.1" @@ -19273,9 +23059,9 @@ __metadata: linkType: hard "whatwg-fetch@npm:^3.4.1": - version: 3.6.19 - resolution: "whatwg-fetch@npm:3.6.19" - checksum: 01dd755492d594c8d71d47811bb3886cdb7d566684daff5ec658cf148fa2418de6b562a94ff8cceaf1cf277bfb99fa6b61258cc20de5053f5817a4d419b5d293 + version: 3.6.20 + resolution: "whatwg-fetch@npm:3.6.20" + checksum: fa972dd14091321d38f36a4d062298df58c2248393ef9e8b154493c347c62e2756e25be29c16277396046d6eaa4b11bd174f34e6403fff6aaca9fb30fa1ff46d languageName: node linkType: hard @@ -19309,16 +23095,33 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.11, which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.2": - version: 1.1.13 - resolution: "which-typed-array@npm:1.1.13" +"which-module@npm:^2.0.0": + version: 2.0.1 + resolution: "which-module@npm:2.0.1" + checksum: 087038e7992649eaffa6c7a4f3158d5b53b14cf5b6c1f0e043dccfacb1ba179d12f17545d5b85ebd94a42ce280a6fe65d0cbcab70f4fc6daad1dfae85e0e6a3e + languageName: node + linkType: hard + +"which-pm@npm:2.0.0": + version: 2.0.0 + resolution: "which-pm@npm:2.0.0" + dependencies: + load-yaml-file: "npm:^0.2.0" + path-exists: "npm:^4.0.0" + checksum: 499fdf18fb259ea7dd58aab0df5f44240685364746596d0d08d9d68ac3a7205bde710ec1023dbc9148b901e755decb1891aa6790ceffdb81c603b6123ec7b5e4 + languageName: node + linkType: hard + +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.2": + version: 1.1.14 + resolution: "which-typed-array@npm:1.1.14" dependencies: - available-typed-arrays: "npm:^1.0.5" - call-bind: "npm:^1.0.4" + available-typed-arrays: "npm:^1.0.6" + call-bind: "npm:^1.0.5" for-each: "npm:^0.3.3" gopd: "npm:^1.0.1" - has-tostringtag: "npm:^1.0.0" - checksum: 9f5f1c42918df3d5b91c4315ed0051d5d874370998bf095c9ae0df374f0881f85094e3c384b8fb08ab7b4d4f54ba81c0aff75da6226e7c0589b83dfbec1cd4c9 + has-tostringtag: "npm:^1.0.1" + checksum: 0960f1e77807058819451b98c51d4cd72031593e8de990b24bd3fc22e176f5eee22921d68d852297c786aec117689f0423ed20aa4fde7ce2704d680677891f56 languageName: node linkType: hard @@ -19355,6 +23158,15 @@ __metadata: languageName: node linkType: hard +"widest-line@npm:^3.1.0": + version: 3.1.0 + resolution: "widest-line@npm:3.1.0" + dependencies: + string-width: "npm:^4.0.0" + checksum: b1e623adcfb9df35350dd7fc61295d6d4a1eaa65a406ba39c4b8360045b614af95ad10e05abf704936ed022569be438c4bfa02d6d031863c4166a238c301119f + languageName: node + linkType: hard + "window-size@npm:^0.2.0": version: 0.2.0 resolution: "window-size@npm:0.2.0" @@ -19365,13 +23177,13 @@ __metadata: linkType: hard "winston-transport@npm:^4.5.0": - version: 4.6.0 - resolution: "winston-transport@npm:4.6.0" + version: 4.7.0 + resolution: "winston-transport@npm:4.7.0" dependencies: logform: "npm:^2.3.2" readable-stream: "npm:^3.6.0" triple-beam: "npm:^1.3.0" - checksum: 43f7f03dfbaeb2a37ddcfadf5f03a6802c77fb8800a384e9aeecce8d233272ed8f18c50f377045a7e154fd6c951e31c9af1bbcd7a3db9246518af42b6f961cc1 + checksum: cd16f3d0ab56697f93c4899e0eb5f89690f291bb6cf309194819789326a7c7ed943ef00f0b2fab513b114d371314368bde1a7ae6252ad1516181a79f90199cd2 languageName: node linkType: hard @@ -19503,6 +23315,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:8.13.0": + version: 8.13.0 + resolution: "ws@npm:8.13.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: 579817dbbab3ee46669129c220cfd81ba6cdb9ab5c3e9a105702dd045743c4ab72e33bb384573827c0c481213417cc880e41bc097e0fc541a0b79fa3eb38207d + languageName: node + linkType: hard + "ws@npm:^3.0.0": version: 3.3.3 resolution: "ws@npm:3.3.3" @@ -19538,6 +23365,21 @@ __metadata: languageName: node linkType: hard +"ws@npm:^8.12.0, ws@npm:^8.13.0": + version: 8.16.0 + resolution: "ws@npm:8.16.0" + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ">=5.0.2" + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + checksum: a7783bb421c648b1e622b423409cb2a58ac5839521d2f689e84bc9dc41d59379c692dd405b15a997ea1d4c0c2e5314ad707332d0c558f15232d2bc07c0b4618a + languageName: node + linkType: hard + "xhr-request-promise@npm:^0.1.2": version: 0.1.3 resolution: "xhr-request-promise@npm:0.1.3" @@ -19613,6 +23455,13 @@ __metadata: languageName: node linkType: hard +"y18n@npm:^4.0.0": + version: 4.0.3 + resolution: "y18n@npm:4.0.3" + checksum: 308a2efd7cc296ab2c0f3b9284fd4827be01cfeb647b3ba18230e3a416eb1bc887ac050de9f8c4fd9e7856b2e8246e05d190b53c96c5ad8d8cb56dffb6f81024 + languageName: node + linkType: hard + "y18n@npm:^5.0.5": version: 5.0.8 resolution: "y18n@npm:5.0.8" @@ -19627,6 +23476,13 @@ __metadata: languageName: node linkType: hard +"yallist@npm:^2.1.2": + version: 2.1.2 + resolution: "yallist@npm:2.1.2" + checksum: 0b9e25aa00adf19e01d2bcd4b208aee2b0db643d9927131797b7af5ff69480fc80f1c3db738cbf3946f0bddf39d8f2d0a5709c644fd42d4aa3a4e6e786c087b5 + languageName: node + linkType: hard + "yallist@npm:^3.0.0, yallist@npm:^3.0.2, yallist@npm:^3.1.1": version: 3.1.1 resolution: "yallist@npm:3.1.1" @@ -19655,6 +23511,16 @@ __metadata: languageName: node linkType: hard +"yargs-parser@npm:^18.1.2, yargs-parser@npm:^18.1.3": + version: 18.1.3 + resolution: "yargs-parser@npm:18.1.3" + dependencies: + camelcase: "npm:^5.0.0" + decamelize: "npm:^1.2.0" + checksum: 25df918833592a83f52e7e4f91ba7d7bfaa2b891ebf7fe901923c2ee797534f23a176913ff6ff7ebbc1cc1725a044cc6a6539fed8bfd4e13b5b16376875f9499 + languageName: node + linkType: hard + "yargs-parser@npm:^2.4.1": version: 2.4.1 resolution: "yargs-parser@npm:2.4.1" @@ -19706,7 +23572,26 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^17.0.0": +"yargs@npm:^15.1.0, yargs@npm:^15.3.1": + version: 15.4.1 + resolution: "yargs@npm:15.4.1" + dependencies: + cliui: "npm:^6.0.0" + decamelize: "npm:^1.2.0" + find-up: "npm:^4.1.0" + get-caller-file: "npm:^2.0.1" + require-directory: "npm:^2.1.1" + require-main-filename: "npm:^2.0.0" + set-blocking: "npm:^2.0.0" + string-width: "npm:^4.2.0" + which-module: "npm:^2.0.0" + y18n: "npm:^4.0.0" + yargs-parser: "npm:^18.1.2" + checksum: f1ca680c974333a5822732825cca7e95306c5a1e7750eb7b973ce6dc4f97a6b0a8837203c8b194f461969bfe1fb1176d1d423036635285f6010b392fa498ab2d + languageName: node + linkType: hard + +"yargs@npm:^17.0.0, yargs@npm:^17.7.1": version: 17.7.2 resolution: "yargs@npm:17.7.2" dependencies: @@ -19756,3 +23641,19 @@ __metadata: checksum: dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f languageName: node linkType: hard + +"zod-to-json-schema@npm:^3.20.5": + version: 3.22.4 + resolution: "zod-to-json-schema@npm:3.22.4" + peerDependencies: + zod: ^3.22.4 + checksum: a949720c165347982a4abf5d612b78bebc2b5fb1217d22e20c024782ce6a9ae0baffe5deb6ba6f961ffa7b28b888c37f744bbfee6d7e9d74f2ec1f94d6968f0d + languageName: node + linkType: hard + +"zod@npm:^3.21.4": + version: 3.22.4 + resolution: "zod@npm:3.22.4" + checksum: 7578ab283dac0eee66a0ad0fc4a7f28c43e6745aadb3a529f59a4b851aa10872b3890398b3160f257f4b6817b4ce643debdda4fb21a2c040adda7862cab0a587 + languageName: node + linkType: hard