From a73b36926ac5cb877f3d496076866522beed1299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Migone?= Date: Thu, 22 Feb 2024 11:05:09 -0300 Subject: [PATCH] chore: add token-distribution package to repo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Tomás Migone --- .gitattributes | 1 - .github/workflows/ci-token-dist.yml | 26 + .gitignore | 7 + package.json | 3 +- packages/token-distribution/.env.sample | 3 + packages/token-distribution/.eslintignore | 5 + packages/token-distribution/.eslintrc | 15 + .../token-distribution/.graphclientrc.yml | 21 + .../.openzeppelin/goerli.json | 135 + .../.openzeppelin/mainnet.json | 135 + .../.openzeppelin/unknown-11155111.json | 135 + .../.openzeppelin/unknown-42161.json | 25 + .../.openzeppelin/unknown-421613.json | 25 + .../.openzeppelin/unknown-421614.json | 25 + packages/token-distribution/.prettierignore | 0 packages/token-distribution/.prettierrc.json | 35 + packages/token-distribution/.solcover.js | 10 + packages/token-distribution/.solhint.json | 14 + packages/token-distribution/.solhintignore | 1 + packages/token-distribution/DEPLOYMENT.md | 151 + packages/token-distribution/LICENSE.md | 21 + packages/token-distribution/README.md | 159 + .../abi/TokenLockWalletABIFull.json | 773 ++ .../abi/TokenLockWalletABIRemix.json | 618 ++ .../2020-11-graph-token-distribution.pdf | Bin 0 -> 134042 bytes .../contracts/GraphTokenDistributor.sol | 161 + .../contracts/GraphTokenLock.sol | 384 + .../contracts/GraphTokenLockManager.sol | 319 + .../contracts/GraphTokenLockSimple.sol | 47 + .../contracts/GraphTokenLockWallet.sol | 206 + .../contracts/ICallhookReceiver.sol | 21 + .../contracts/IGraphTokenLock.sol | 54 + .../contracts/IGraphTokenLockManager.sol | 56 + .../L1GraphTokenLockTransferTool.sol | 319 + .../contracts/L2GraphTokenLockManager.sol | 159 + .../L2GraphTokenLockTransferTool.sol | 71 + .../contracts/L2GraphTokenLockWallet.sol | 66 + .../contracts/MathUtils.sol | 9 + .../contracts/MinimalProxyFactory.sol | 79 + .../token-distribution/contracts/Ownable.sol | 71 + .../contracts/arbitrum/ITokenGateway.sol | 75 + .../contracts/tests/BridgeMock.sol | 118 + .../contracts/tests/GraphTokenMock.sol | 42 + .../contracts/tests/InboxMock.sol | 193 + .../contracts/tests/L1TokenGatewayMock.sol | 168 + .../contracts/tests/L2TokenGatewayMock.sol | 177 + .../contracts/tests/Stakes.sol | 214 + .../contracts/tests/StakingMock.sol | 128 + .../contracts/tests/WalletMock.sol | 62 + .../tests/arbitrum/AddressAliasHelper.sol | 46 + .../contracts/tests/arbitrum/IBridge.sol | 72 + .../contracts/tests/arbitrum/IInbox.sol | 88 + .../tests/arbitrum/IMessageProvider.sol | 32 + packages/token-distribution/deploy/1_test.ts | 32 + .../deploy/2_l1_manager_wallet.ts | 73 + .../token-distribution/deploy/3_l2_wallet.ts | 27 + .../deploy/4_l1_transfer_tool.ts | 79 + .../token-distribution/deploy/5_l2_manager.ts | 79 + .../deploy/6_l2_transfer_tool.ts | 69 + .../token-distribution/deploy/lib/utils.ts | 41 + .../deployments/arbitrum-goerli/.chainId | 1 + .../L2GraphTokenLockManager-Testnet.json | 1161 +++ .../L2GraphTokenLockTransferTool.json | 110 + .../L2GraphTokenLockWallet.json | 1156 +++ .../b5cdad58099d39cd1aed000b2fd864d8.json | 152 + .../deployments/arbitrum-one/.chainId | 1 + ...L2GraphTokenLockManager-Foundation-v1.json | 1161 +++ .../L2GraphTokenLockManager-MIPs.json | 1161 +++ .../arbitrum-one/L2GraphTokenLockManager.json | 1161 +++ .../L2GraphTokenLockTransferTool.json | 110 + .../arbitrum-one/L2GraphTokenLockWallet.json | 1156 +++ .../b5cdad58099d39cd1aed000b2fd864d8.json | 152 + .../deployments/arbitrum-sepolia/.chainId | 1 + .../L2GraphTokenLockManager.json | 1198 +++ .../L2GraphTokenLockTransferTool.json | 110 + .../L2GraphTokenLockWallet.json | 1156 +++ .../095bd30babc75057be19228ca1fd7aa4.json | 152 + .../deployments/goerli/.chainId | 1 + .../goerli/GraphTokenLockManager-Testnet.json | 932 +++ .../goerli/GraphTokenLockManager.json | 926 +++ .../goerli/GraphTokenLockWallet-Testnet.json | 1101 +++ .../goerli/GraphTokenLockWallet.json | 1083 +++ .../goerli/L1GraphTokenLockTransferTool.json | 612 ++ .../3c1e469b4f9ba208577ab7c230900006.json | 98 + .../b5cdad58099d39cd1aed000b2fd864d8.json | 152 + .../deployments/mainnet/.chainId | 1 + .../GraphTokenLockManager-Foundation.json | 926 +++ .../mainnet/GraphTokenLockManager-MIPs.json | 932 +++ .../GraphTokenLockManager-Migrations.json | 926 +++ .../mainnet/GraphTokenLockManager.json | 926 +++ .../GraphTokenLockWallet-Foundation.json | 1083 +++ .../mainnet/GraphTokenLockWallet-MIPs.json | 1101 +++ .../GraphTokenLockWallet-Migrations.json | 1083 +++ .../mainnet/GraphTokenLockWallet.json | 1083 +++ .../mainnet/L1GraphTokenLockTransferTool.json | 612 ++ .../5ad03e035f8e3c63878532d87a315ef8.json | 83 + .../6f5e8f450f52dd96ebb796aa6620fee9.json | 98 + .../a72ab6278ade6c5c10115f7be2c555c9.json | 98 + .../b5cdad58099d39cd1aed000b2fd864d8.json | 152 + .../f0757d7c1c560a6ae9697525709a3f5b.json | 65 + .../deployments/rinkeby/.chainId | 1 + .../rinkeby/GraphTokenLockManager.json | 926 +++ .../rinkeby/GraphTokenLockWallet.json | 968 +++ .../deployments/rinkeby/GraphTokenMock.json | 552 ++ .../a72ab6278ade6c5c10115f7be2c555c9.json | 98 + .../deployments/sepolia/.chainId | 1 + .../sepolia/GraphTokenLockManager.json | 969 +++ .../sepolia/GraphTokenLockWallet.json | 1101 +++ .../sepolia/L1GraphTokenLockTransferTool.json | 636 ++ .../095bd30babc75057be19228ca1fd7aa4.json | 152 + packages/token-distribution/hardhat.config.ts | 192 + .../token-distribution/ops/beneficiary.ts | 78 + packages/token-distribution/ops/create.ts | 580 ++ packages/token-distribution/ops/delete.ts | 88 + .../token-distribution/ops/deploy-data.csv | 5 + packages/token-distribution/ops/info.ts | 758 ++ packages/token-distribution/ops/manager.ts | 164 + .../ops/queries/account.graphql | 17 + .../ops/queries/curators.graphql | 25 + .../ops/queries/network.graphql | 6 + .../ops/queries/tokenLockWallets.graphql | 20 + packages/token-distribution/ops/results.csv | 0 .../ops/tx-builder-template.json | 15 + packages/token-distribution/ops/tx-builder.ts | 31 + packages/token-distribution/package.json | 84 + packages/token-distribution/scripts/build | 6 + packages/token-distribution/scripts/coverage | 6 + packages/token-distribution/scripts/flatten | 24 + .../token-distribution/scripts/prepublish | 26 + packages/token-distribution/scripts/security | 17 + packages/token-distribution/scripts/test | 62 + packages/token-distribution/test/config.ts | 101 + .../test/distributor.test.ts | 201 + .../test/l1TokenLockTransferTool.test.ts | 674 ++ .../test/l2TokenLockManager.test.ts | 459 ++ .../test/l2TokenLockTransferTool.test.ts | 262 + packages/token-distribution/test/network.ts | 95 + .../token-distribution/test/tokenLock.test.ts | 770 ++ .../test/tokenLockWallet.test.ts | 377 + packages/token-distribution/tsconfig.json | 22 + yarn.lock | 7086 +++++++++++++---- 141 files changed, 46625 insertions(+), 1383 deletions(-) delete mode 100644 .gitattributes create mode 100644 .github/workflows/ci-token-dist.yml create mode 100644 packages/token-distribution/.env.sample create mode 100644 packages/token-distribution/.eslintignore create mode 100644 packages/token-distribution/.eslintrc create mode 100644 packages/token-distribution/.graphclientrc.yml create mode 100644 packages/token-distribution/.openzeppelin/goerli.json create mode 100644 packages/token-distribution/.openzeppelin/mainnet.json create mode 100644 packages/token-distribution/.openzeppelin/unknown-11155111.json create mode 100644 packages/token-distribution/.openzeppelin/unknown-42161.json create mode 100644 packages/token-distribution/.openzeppelin/unknown-421613.json create mode 100644 packages/token-distribution/.openzeppelin/unknown-421614.json create mode 100644 packages/token-distribution/.prettierignore create mode 100644 packages/token-distribution/.prettierrc.json create mode 100644 packages/token-distribution/.solcover.js create mode 100644 packages/token-distribution/.solhint.json create mode 100644 packages/token-distribution/.solhintignore create mode 100644 packages/token-distribution/DEPLOYMENT.md create mode 100644 packages/token-distribution/LICENSE.md create mode 100644 packages/token-distribution/README.md create mode 100644 packages/token-distribution/abi/TokenLockWalletABIFull.json create mode 100644 packages/token-distribution/abi/TokenLockWalletABIRemix.json create mode 100644 packages/token-distribution/audits/2020-11-graph-token-distribution.pdf create mode 100644 packages/token-distribution/contracts/GraphTokenDistributor.sol create mode 100644 packages/token-distribution/contracts/GraphTokenLock.sol create mode 100644 packages/token-distribution/contracts/GraphTokenLockManager.sol create mode 100644 packages/token-distribution/contracts/GraphTokenLockSimple.sol create mode 100644 packages/token-distribution/contracts/GraphTokenLockWallet.sol create mode 100644 packages/token-distribution/contracts/ICallhookReceiver.sol create mode 100644 packages/token-distribution/contracts/IGraphTokenLock.sol create mode 100644 packages/token-distribution/contracts/IGraphTokenLockManager.sol create mode 100644 packages/token-distribution/contracts/L1GraphTokenLockTransferTool.sol create mode 100644 packages/token-distribution/contracts/L2GraphTokenLockManager.sol create mode 100644 packages/token-distribution/contracts/L2GraphTokenLockTransferTool.sol create mode 100644 packages/token-distribution/contracts/L2GraphTokenLockWallet.sol create mode 100644 packages/token-distribution/contracts/MathUtils.sol create mode 100644 packages/token-distribution/contracts/MinimalProxyFactory.sol create mode 100644 packages/token-distribution/contracts/Ownable.sol create mode 100644 packages/token-distribution/contracts/arbitrum/ITokenGateway.sol create mode 100644 packages/token-distribution/contracts/tests/BridgeMock.sol create mode 100644 packages/token-distribution/contracts/tests/GraphTokenMock.sol create mode 100644 packages/token-distribution/contracts/tests/InboxMock.sol create mode 100644 packages/token-distribution/contracts/tests/L1TokenGatewayMock.sol create mode 100644 packages/token-distribution/contracts/tests/L2TokenGatewayMock.sol create mode 100644 packages/token-distribution/contracts/tests/Stakes.sol create mode 100644 packages/token-distribution/contracts/tests/StakingMock.sol create mode 100644 packages/token-distribution/contracts/tests/WalletMock.sol create mode 100644 packages/token-distribution/contracts/tests/arbitrum/AddressAliasHelper.sol create mode 100644 packages/token-distribution/contracts/tests/arbitrum/IBridge.sol create mode 100644 packages/token-distribution/contracts/tests/arbitrum/IInbox.sol create mode 100644 packages/token-distribution/contracts/tests/arbitrum/IMessageProvider.sol create mode 100644 packages/token-distribution/deploy/1_test.ts create mode 100644 packages/token-distribution/deploy/2_l1_manager_wallet.ts create mode 100644 packages/token-distribution/deploy/3_l2_wallet.ts create mode 100644 packages/token-distribution/deploy/4_l1_transfer_tool.ts create mode 100644 packages/token-distribution/deploy/5_l2_manager.ts create mode 100644 packages/token-distribution/deploy/6_l2_transfer_tool.ts create mode 100644 packages/token-distribution/deploy/lib/utils.ts create mode 100644 packages/token-distribution/deployments/arbitrum-goerli/.chainId create mode 100644 packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockManager-Testnet.json create mode 100644 packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockTransferTool.json create mode 100644 packages/token-distribution/deployments/arbitrum-goerli/L2GraphTokenLockWallet.json create mode 100644 packages/token-distribution/deployments/arbitrum-goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json create mode 100644 packages/token-distribution/deployments/arbitrum-one/.chainId create mode 100644 packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-Foundation-v1.json create mode 100644 packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager-MIPs.json create mode 100644 packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockManager.json create mode 100644 packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockTransferTool.json create mode 100644 packages/token-distribution/deployments/arbitrum-one/L2GraphTokenLockWallet.json create mode 100644 packages/token-distribution/deployments/arbitrum-one/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json create mode 100644 packages/token-distribution/deployments/arbitrum-sepolia/.chainId create mode 100644 packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockManager.json create mode 100644 packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockTransferTool.json create mode 100644 packages/token-distribution/deployments/arbitrum-sepolia/L2GraphTokenLockWallet.json create mode 100644 packages/token-distribution/deployments/arbitrum-sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json create mode 100644 packages/token-distribution/deployments/goerli/.chainId create mode 100644 packages/token-distribution/deployments/goerli/GraphTokenLockManager-Testnet.json create mode 100644 packages/token-distribution/deployments/goerli/GraphTokenLockManager.json create mode 100644 packages/token-distribution/deployments/goerli/GraphTokenLockWallet-Testnet.json create mode 100644 packages/token-distribution/deployments/goerli/GraphTokenLockWallet.json create mode 100644 packages/token-distribution/deployments/goerli/L1GraphTokenLockTransferTool.json create mode 100644 packages/token-distribution/deployments/goerli/solcInputs/3c1e469b4f9ba208577ab7c230900006.json create mode 100644 packages/token-distribution/deployments/goerli/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json create mode 100644 packages/token-distribution/deployments/mainnet/.chainId create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Foundation.json create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockManager-MIPs.json create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockManager-Migrations.json create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockManager.json create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Foundation.json create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-MIPs.json create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockWallet-Migrations.json create mode 100644 packages/token-distribution/deployments/mainnet/GraphTokenLockWallet.json create mode 100644 packages/token-distribution/deployments/mainnet/L1GraphTokenLockTransferTool.json create mode 100644 packages/token-distribution/deployments/mainnet/solcInputs/5ad03e035f8e3c63878532d87a315ef8.json create mode 100644 packages/token-distribution/deployments/mainnet/solcInputs/6f5e8f450f52dd96ebb796aa6620fee9.json create mode 100644 packages/token-distribution/deployments/mainnet/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json create mode 100644 packages/token-distribution/deployments/mainnet/solcInputs/b5cdad58099d39cd1aed000b2fd864d8.json create mode 100644 packages/token-distribution/deployments/mainnet/solcInputs/f0757d7c1c560a6ae9697525709a3f5b.json create mode 100644 packages/token-distribution/deployments/rinkeby/.chainId create mode 100644 packages/token-distribution/deployments/rinkeby/GraphTokenLockManager.json create mode 100644 packages/token-distribution/deployments/rinkeby/GraphTokenLockWallet.json create mode 100644 packages/token-distribution/deployments/rinkeby/GraphTokenMock.json create mode 100644 packages/token-distribution/deployments/rinkeby/solcInputs/a72ab6278ade6c5c10115f7be2c555c9.json create mode 100644 packages/token-distribution/deployments/sepolia/.chainId create mode 100644 packages/token-distribution/deployments/sepolia/GraphTokenLockManager.json create mode 100644 packages/token-distribution/deployments/sepolia/GraphTokenLockWallet.json create mode 100644 packages/token-distribution/deployments/sepolia/L1GraphTokenLockTransferTool.json create mode 100644 packages/token-distribution/deployments/sepolia/solcInputs/095bd30babc75057be19228ca1fd7aa4.json create mode 100644 packages/token-distribution/hardhat.config.ts create mode 100644 packages/token-distribution/ops/beneficiary.ts create mode 100644 packages/token-distribution/ops/create.ts create mode 100644 packages/token-distribution/ops/delete.ts create mode 100644 packages/token-distribution/ops/deploy-data.csv create mode 100644 packages/token-distribution/ops/info.ts create mode 100644 packages/token-distribution/ops/manager.ts create mode 100644 packages/token-distribution/ops/queries/account.graphql create mode 100644 packages/token-distribution/ops/queries/curators.graphql create mode 100644 packages/token-distribution/ops/queries/network.graphql create mode 100644 packages/token-distribution/ops/queries/tokenLockWallets.graphql create mode 100644 packages/token-distribution/ops/results.csv create mode 100644 packages/token-distribution/ops/tx-builder-template.json create mode 100644 packages/token-distribution/ops/tx-builder.ts create mode 100644 packages/token-distribution/package.json create mode 100755 packages/token-distribution/scripts/build create mode 100755 packages/token-distribution/scripts/coverage create mode 100755 packages/token-distribution/scripts/flatten create mode 100755 packages/token-distribution/scripts/prepublish create mode 100755 packages/token-distribution/scripts/security create mode 100755 packages/token-distribution/scripts/test create mode 100644 packages/token-distribution/test/config.ts create mode 100644 packages/token-distribution/test/distributor.test.ts create mode 100644 packages/token-distribution/test/l1TokenLockTransferTool.test.ts create mode 100644 packages/token-distribution/test/l2TokenLockManager.test.ts create mode 100644 packages/token-distribution/test/l2TokenLockTransferTool.test.ts create mode 100644 packages/token-distribution/test/network.ts create mode 100644 packages/token-distribution/test/tokenLock.test.ts create mode 100644 packages/token-distribution/test/tokenLockWallet.test.ts create mode 100644 packages/token-distribution/tsconfig.json 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/workflows/ci-token-dist.yml b/.github/workflows/ci-token-dist.yml new file mode 100644 index 000000000..7751a4c38 --- /dev/null +++ b/.github/workflows/ci-token-dist.yml @@ -0,0 +1,26 @@ +name: CI + +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/.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/package.json b/package.json index 6d42981d0..fb262d3d6 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,8 @@ "packageManager": "yarn@4.0.2", "workspaces": [ "packages/contracts", - "packages/sdk" + "packages/sdk", + "packages/token-distribution" ], "scripts": { "postinstall": "husky install", 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/.eslintignore b/packages/token-distribution/.eslintignore new file mode 100644 index 000000000..d560011c6 --- /dev/null +++ b/packages/token-distribution/.eslintignore @@ -0,0 +1,5 @@ +build/ +cache/ +dist/ +node_modules/ +reports/ diff --git a/packages/token-distribution/.eslintrc b/packages/token-distribution/.eslintrc new file mode 100644 index 000000000..5e4aa09f9 --- /dev/null +++ b/packages/token-distribution/.eslintrc @@ -0,0 +1,15 @@ +{ + "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": "warn", + "@typescript-eslint/no-inferrable-types": "warn", + "@typescript-eslint/no-empty-function": "warn" + } +} 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/.prettierignore b/packages/token-distribution/.prettierignore new file mode 100644 index 000000000..e69de29bb diff --git a/packages/token-distribution/.prettierrc.json b/packages/token-distribution/.prettierrc.json new file mode 100644 index 000000000..81a7194cb --- /dev/null +++ b/packages/token-distribution/.prettierrc.json @@ -0,0 +1,35 @@ +{ + "printWidth": 120, + "useTabs": false, + "bracketSpacing": true, + "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, + "explicitTypes": "always" + } + } + ] +} 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/.solhint.json b/packages/token-distribution/.solhint.json new file mode 100644 index 000000000..e52cf9346 --- /dev/null +++ b/packages/token-distribution/.solhint.json @@ -0,0 +1,14 @@ +{ + "extends": "solhint:recommended", + "plugins": ["prettier"], + "rules": { + "prettier/prettier": "error", + "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/token-distribution/.solhintignore b/packages/token-distribution/.solhintignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/packages/token-distribution/.solhintignore @@ -0,0 +1 @@ +node_modules 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 0000000000000000000000000000000000000000..cc11beb06b46f95b24ce77b44842d580f79d3e88 GIT binary patch literal 134042 zcmd?R1z42(_BKpQcZ1TPNKL?iba%IO_t4!T4NAAtEmD%wQc?oaAPp)l5`y42pzMA2 z+57*#`<(s1&h_r|aVd*gv*wwZ`&rNWt#z;U{1}wPBv=7#oahWMcPh@&xv4p*?TxL` z`S_^W<;nVHy|nxP8_pgX%bnHkxkdt?qh z)N!8UBKF&S(LN``ixtcpu22YSv18&ra!K%F!jY!3jI5qfGNv7Kyx2Qga)Oho+vajL zPa5od@GRUJZoi9%N{T~d`8x=OD#+Yu`2oLJ zullAOovqr+QroJlG?D`lFQCn-M-mz)lbiLwRVfGg30o1R?idr!?_!8{MJtCLY$xF zd-pk66?@Hr&ZE(zGPOza)Vf0=v5R-H3C+fzxLB=1cSM2_1fmc*++W7=a z`njzY4^wDT(n@~>9>c_gG%UQ%M2$IGVSXXv-2%DrCqg)S3@Mf-gN$_1y!j3a`1CUH zw}px_`&Ce591|7{r*J=*Ohtt(DdqK=exAmF+^(%1Q^Dq|ld{C{Z%hNsDoewAF8~9y zb!fNG=LgAFCMK%e_2R*7ZZ@I!rb9uN-rtF##TFN(=-{=`j%wA zq7369njWXd;e>TdMLK6fuDXxsWwS{KVwTqhfzQ<71s#NgzPD>Js=f_groYrMF*ELQ z$XESPMXdv?NbM4%kGAISG}QcGlU{jov+{v&Ef;1i9T?(|RqH-6+9AFZ5$saK9?ilq z1UA!6OfN;OSXEEkZq&k$EF7LjSD*e0Y0j@Fc{v z)#7d?K^Cp2$voL&m3`WN)k)fcReM8tyf1ksjwoF0ewftW_-0L_CJl)njn^ibxZkF> zKfd2)X&28tw8XhPLp@8$KmgMOg4H}%5ElhpbKURuEm-1Gi?nBI!}ZAt5O=KE(p^4% z6Wl0s+W9udl(+pEYvSFL!@@gE#S$dVUURx}b8b%S1*k`6lrK7#UDOo^)Uv^9w$>tA zQ>|ngtnWlom#p>AbEu#e$R7*0yq!jOT}`L!Dn59&U54RIIgCQJ8%F(Jh30P3;>c@u zO$>P7UzLaGEkL+2>#f{n^;y~GCVYCbw+NYUdF&(m+J@q^FB#o>YN+w*K7`-5{y<3LWy6;${3)2W#%okz;7QJKEvHHo@LB?!ajK6~O)67%U|>N2lzzM* ztMSn*cqH{gW_%>iuGBHDIEpmu#e1_X3{+ws3Ib@6{kO6{r}~J@n?f4xDH9a8ed8#W z_upDoE7E-pp|MQyK@v>&85>gM*#u4bWtuFHy*FymwnLl^l=RB$})YL;SLRrW8rJyIU3spJn`Eq z9!#i!h5=e$b-ugfxR4q7T^%tm*!yRLUwr`2fsfa|%f8@7V)_tLd)_ZFKCs6&tQUAr zc8t8v{l!1U!l;^O{|q`mSo2vR=-xUB<9MYZ&bVf4-{}PZYRVYHD$60pLcVwLiq~d3 zZ;UEEYB79O05;n46JDMng&I5K4e9U-%9XE4)H=-F)vCqyPitwQ)fV3(`!WsiWV)gh zYV^9FW@5L2KM+4ty0bi$(X^K{CWt)HnW&2D$#h1?0-ArJh;nFsGzvzMnb<7?O#7sI zl8Xv{)NmRUatH(0iwAkNojiZFgo)}dBexIx&Or0*5VbcnPtDPQ96Efw&rAFCs30?- zba7LK8q|Vi@uC@xDyAaQ8kt?edpr^~HC{Rfb!S%q|Senu`8Dcai%+Z37q5HIyE`%(YU()1bi6FH2uMqLILUH>T z7!nkv)$=QGGPVbSV&*KOsJFrtYFLdG6++F%j`SkEt=9+G`+$O*(Pg~LRE%l)Jug%m z7RNr*Q6^Nr#EKMzl)d7XjL*sNVZuVsd6O(hf)?n#)nKLuU2Q0^J&tgTo;3{t5q=|E z(a&HiQYhoCJFo1|bY!7*jy0m7q&$=3;zer_+$62({c@?zuXo}8>FnU12T{??$hJ|R zWO%o_5>0k6W=(Hu_fX(;itb*-#TwIs;G+`B?l5sw;ZMrTUvJS;ilxYA!5jlcmX)^h zwouhGYKqqa50b#)7ck!eLB&mnpZ~zILP368beEg)c%;d$zU2J-cBmlqJF@p1BlmOq znSqgp&&}VvmL6Bip|^o)E)Gm&Fr~byPYV*ggQ!~8&hK&@3O%ouBSs6-!Kfk)&wqzn z*Bu?P4W2<)#i13-zk3QY4dRk4Dn+-&aZKP})e_sF?2_Q-b4j=LwGJ|1_LSTI?o{)f z{p?t}S~Jy5zp5D?$Kwdo?faNa1G4wX+exwB;%X@HZGJeNpPY*Hp9`pCN@*YcYo$^4Sd@PwjHlf~zJr3N_;+cSvrm=rfj2 z4GlU%yv~GiWRiF?!6xSq*n0RGVwv6KddM^1 z$4R=;-YP7sl1aLSGc)6Y51R>2@PZ<;ivzOHEDO|El!oqAz1Vmw-x^lDq3gCbc_5pe zZn7&({M?DI>l-5jk33gtV@O~A29WR($pdxe)JF~dPY+}ll$}fPuoZX98c9#`PZ=JU zHX0P2`JRL4LOA+&Tb8ms9`DPTeO%w_x_GS;hObcKiv~F%fZmbe#^%Ik%$34jqim28 zH4)=Z60pe~x6KQY4OhTt6BV{&D0)y_MGA8XnFJ&wB8tkVBEoG>1zlbi$Er_BO=yYtmvk4>Vw=JY#L!>w{y&pc^Z16HFdG2;}r5bOqipd z4&S3mYG-OCQ@LEWb$Vzu@(uQ>ejDUg=%1eU(6o=0pH^+QC?0Eohb!ky=FuR$_*Igv z4)nB{dx-K_vDt9QZT*8xtl)6+_1M&T=eqqAhN39NT`{Ar)*S)XG(DGHo90Ao$3u$| zTx+ZZ-)FO!lBm6Nj@FR;U9QV-OSc3QmlJe=3*aVILSA=M<0e|p#)B7@-_nAc=9+fK z6klB6q47y*;XCluc@$Tc)UV~Xe9uI=Gh+GOlEVFtBPADWVDp9oK@%wW5?A8GAQ&vF z_@4D_mtU6zAD7H+%_|B;_myY;x5$8p?u+(%YyNUXHq0Pb$agd zntRZWop(n$f|vV|0}LM9fM*^qyyE^3LZXk}#cT~{ZSCg?I`O?8SxDtdl|R)vSG}!i zls%OKO`cl*DEnYmnCsH$^P8iWj4543#I%CJTlGhEfxFK&IwrU!-ZxJ4FZm%h7QZA+ zuHx1I9E&(GAJ6?^wgbmA{n9O}?Gw66>`S5q17Obu>qeN0k#7_IY8^4Y2DUR#q$av- z=QAD+N=19})%O$_nw<0SDKd=tim3ULeF1}6s8}&Thop;;%fSnzHRp@+?_}25_L&YH zF@k|7DZLrrmOPSp1L3U%9+Sk)KcBXIKN1YHT=EbcQKZ~^#)l6zB8hXhuFem&#v~#t zO|Gictj>o z0DI!cZ*~cLsLMZCo3nDTa!>;}ZmNu{Bbc)Su5^Ik>VQ`|;BR#RRsb~sbfbg41MJ_= zPYM9T)Hk(^nx}&qHM=krYVUIWxm8__U9MGfR#2NC8W$&56Bi{TCo|Z`i)g#Y0?|NJy2E>`x? zs~28)%Ha_S7S&5msS(%urNQzu3e}*^} zGiQ5OClfPg>MJk$@t&&x5cZv^!B^HlmWivFf4zjLPy?>Q`ib(q`aaR;vFyZ>D2sKPQ2IIc!k1$V_D%dM?3+BOb`ra{nPX%*KYADriMWHE}2u zUtOho>--2(!(LNsir08oVt%V2jfRJ}hPUQ$a67UF^U}S487GgsY^wj6bh1-chHiDg zfmjaMq6^Dg&urUVuC-Z)Td{_PK*keKj9AZmt`?5es)mL%mlNx z?gE#s-b;!}gYTp7cqe0RZDGPG3+5K0XlZ7rvH z>mt}o)Ev7eqe+28X-F!C@tgFoi`8WB^rd&y5au&H9fj}8fAww|tABt{0DUFgrEB6f z$1Jdk-sv+qC4Mc9cE}U2=TJ=^-BUsmo#`pT_Q6W{JAL@f5EfSTG&HROAd4p2ccO07 z7KaG%C-^8#=lW{Z%mUze&r%9dQ#`rLK(2&a>aro}_!EY2?O2e;Sy;~Od;KG-^q~>o zi)FnD*P&td!}7eLm@P)_Pbyh%RVNr4Cm9P$6V00C#wTuu4%ODZp%_qN`Gs2dp+3J; zqLTY{qC~w>i!c0S*d9r_(sVpBdaIUV2G6X=D!k@5XRo!>`ohhw4SqDEAi+x~5NGjZ z__^k}e9TB$#lp*>Q}_EM?*@Xr3~^2qmtWn@{P2ujtS*4e8Ui^zax&eQ1XVU;D6^zH zhWYSnG(+E3n?-%j>J%{5T@ns=*t*>q^i|~+p6H&`mVu1~W*oCaZqPZ0GqC-jhK~uK zPa_gMA}_+SuYFI|gx;}1t>hkeM071Cl!`l>)&c)MeWiAqxco3T))(%6gD!)@IH}yB{&Jnw`LINP4*k&nhHB}gx02ynh%I%cIN}e!8A_MOqIEE zp#A4edG}u-dNZ$3rw+FF*{a~VRTH7%aWj@}K0Nre!K3$9fJUQocz_$_Y;q#X=>3JV! zxkTsKdo3a>xFa}R8|HdE>!Lw<1J9Yo61lk?1l74>j+_ASJLsB@g+P-{()En{6g$S8&Xj<@55VcX31)KtLU8PVbWlvzqtdkl(=+**4BezqtX z2kGe`q&2Gy()M%sTU27~E%|nt&&dFAYG#>9aQx~DA~L8!nFJ9L0NEtCyF^;4WF08l zxRR!otY`|fbk8qPgea5fdd($_iSC84^sDvsq){b*NCzKA58FJ&Wg^``!cX$P-D*4k zaHj^JlB`$_{Si4;=*|+~ZoP$s7dYX;geSDdB-OT;2g2V}AfE4Tx~=*#PJMyY*xhu< zK&jA`jZI?*?m%ln-Oj?G7XIa@Tjvh=d29_zkE-v|vz)Kq4Q_}W<9IU8l)H7Yvhaw7 zxQ^>}!}}!xxbBJ4mYL=p+i=mW@DA(;wnEs=O^oPux(zbIM4Ii4#wfR9*!IzzHgE4BK16t`bB zEe?Aog`2@_vCk%8=GccC@wU5W?$8aVa=S?+Q+x)F0y=$r&VF9tHa=qFHtI#}lV{?- z_q^wtN6wqg8}2@$@@mqi!$;l=bXBeJ{YF0>X}|t11e5Hh;&UWNhpm2B1rfTeum?;IVu6%f!>@sL{&FHldzFBd9)_maCQk*DTE%ej z4bPl7Hhn40+4KMT|-;A_=Q@}>gva5oHp9A)U;^trXdSS-Z|Ha;zy~qK!<~8e_ET391t$z zSkq+hUXN+R>n+e(r?91GaB`dYC3Wp>t(UqFL?v0U6)9;qYXGTi6yEHg~4& z69CG^shD7#jJ}hDzh=KcC&rU1>Ct>M*v zFU}T>wc_?+cYt@Uc?uhvCYtaYJD?$Zq~)Wr^doBIee6%OA1mu`0zldM2K!X}+8RjoTt;sw+-_*2xT=J2&(ReTpXqVV`-IwPLqnJIRyzuz0{3hL5G9hHm@B4{Lj1QrPO;Uc zuY-ur6^Po-(q7XuRnFWEcZTLVuYAcY7@Wwro#%3Gw$7?b!M8TlCgu^8a;o*64th5k zIuQXG!V8?*LOqCP1(L8EWiuOG}W>c5lpqxw!rO;A=5M(ggDXqUQ6fX0< zW-9>kt}AKR(3|GauXAjzhfYd6vpq5Pg3s~hj_1sa-LO25@{7PjVXKI1Z#je4>JO$^ zdHs>c?UkByT$60yTu$uGHaU{(LGCZ|*J0&0m)fMT*`1@vw#O(g!l4SEFjEp?yP$R4 z_B_6vAB)VSl~0&CZ{v8hD?^bTA#%se$m_mtOcbU6;~@v{A?`jriRp9Gz)&RX{S72S z&p>3fcLA#zr*U9ropnIxrq6f5c=$bDewv9yc47qS8gSTUSP4nu_Q z0$9=GNkC0+*!X)7CA`MZ?7*}L%mQZFs+KRh^>z(er~j#$CfaB`s zRf-T)z!Pu2#8AI!M}O%EmwtFxEI1#bP6lK$-l^9$=XQY@GFJBz9@Fd-y`yv=8F{_e z^ydZF%ObyFg2gw!b6}@LJI6Qp{^>bVu_3mqsqvPtz9QJL$%~W^8%v_1u28#)tx<+Z zJSf@%Jyj*nu_xC?$;hOyVX@2E41--=rLcuC5w;Lc@}$MF=!>ns(+N01h$a5+>Ayrk z@da7%YfYdlGCW@;Z+k=?AWV3t1$TaA_ttxggLx|_@>(jq<=fzc#1>X;M01efgK&0a zQz9O0+4+}USmbaX$4|);jLbPsIqGyDDq{A|M%9f{;i&#gC&E!C&jg1OnAo#OT&HhrFDI>1f zVu?>R&zT25=hwJ>p(Iz0FcRlL5E@BT2LCNE7`x&U(1vg%Si(&G)gfXB8$Q9zpZX)u zZAZhI9ra4KZ`k*N&^*eb5w+M=pVG{UMco-wLB`gWV&jFQ@3kpwNZv2Ol_pUUErA3R zpQ+@J_}*GDGfkgcIlXG3`ik)$I6)xDBr{WX=|L4uyOA8x+S2C-(9FuY8?Pqeu7% zKqG5|AkIU%5xxP7r$nHU!ND4*;p3Tzvkk%f zqyLUbRLdTC#mD@XtiL83ezNso0GR8Bv4N4*H^js>v+=({*Z)~+{*P(>|B3Vh(7-!~W zWa8q?E_u}lP`jf4Eytie}c~k|Anpy*B`^o4f%oHjf8OhfSKzLVCMS8 z^uHYDztA>;{2pci7p&_9b7LT^C-#fH^4Tl>Kl}5I^2Ye@i!|4tap=F$TH*d5kcN5k zHF!4?=FvYu{U?{cQQjE;mm~cbdM`Y`M;gcl^JSRtf?z$}UnD0d^|c-*e}MTjM&BrJ zjQ_q!L;j3U-!x~g`sn{+mkaO*z3U%P!`iLaQ2&&iJU^lSr#9CQs9`;@pT_^?P~Xfs z{5w$pL4%tI=FG5R1|Y|;k`tzb{ksys@#&ws8`Hln&VOo-fb-W(^j~*r;P0ac3_LCl zt{*u6lvn-5YfS$scKp;`;|w$XFUR>GTao{2==g&UIhc!^nv)Ae%?W~e@Qnm>QeW#~ z@;4rRqr5Tx`$GL^G7rw*_rw46fDzzFr};M}%MYkwee!Fle@ZaVPpJPXO8>JY#UgBQq64dnR;2@BiTdYJr;SKlaajQ_q+|Cs`j^Dh*LfIp}Ze?SdO z>#m{xDPe;ZKTrk#5!B#cjQ`7_{tHDS;E$?A4%i47Hw(xJ% zH^zTMs5OmjZOvSMkRJdr$Dc^7IsZbj2>63)5yrJ$Bh3k;nXVAOmN2BR_5Y0cjq=9$ zZ-}_O5fnD@<@5t`(4Uzf<@^gpBj69JMi4BqhK;gPgF!IlZzL?ayw=0yZ+!eld1L%H zMEtit{-@HCzfe2^|DbpTalw2WmXd&B>*X)<%I~lAF!@`=e=2W`|MrOU{F$io7ivi0 zAJmXQSat&B1i&H+Y$d#rAP_9B!}Kuu8^mvvH^zT=!~xuY0&y7a`ENH1fPYX;UV{jR z{6PFhf?(z4HR3ll;|&+}Q+bUz%=rHwi2sGU68HyoB>)11rGPM=6;|NC_Wn<6kVrj-|X9cygGqPoc-Q?oo z$$HcAV*fKi;igEu8fgb!MTn~rZ{W>5I`C#78+bGB4!oInhut#q)A+~4JM2|A6XLK% z@8?rD`yhaBjtsgvGHh}DVFQcJKmWKnGAu9rsku2a=;p|vn_; zKO)z^IcI-8q<)16HLQF1pBl8kZb1Kd)89_o1AkQI*M!N{sQq>OSB3hzJqZ)nu)&y* zEA*&gG4@(q0|vWS~zix@4yI@ZN!S`Qm3wnG^ z^M2nZWnNTyDVxwVSO`oSv)=LlyT3S#rOzyoN(2sOiJsL7AP-884H_3=6_dxr6 z^4{Jf$jfoNacjrMVtsvsVvKu<4X-Nv_;s*PjO&_waSx>jCpX_b!@4kU@S@>@1P8G9 z-a3G4VcVFBbgi2&jBu@dI~kxV-D49Lr=!^8v^0OXWr`tqI?TMT+^hPA?77VXb5Yak zY*wJc)ZF@ngR9@y-dmyPA349xGk;T@*Hrli_x-!_#Tl)-^2>M`ZuN7C1SAXVnL4qd5RE2{fa<d91@U(6S9X-`oCx)N)@wm%zIZ3OQrl;hSlmL-m;0To!`p?Yq~BC@=O> zjENM!O;i$3mAQr(J(y`wc~i$}sL?+5jyQRf1HUn;2k`@3RHFe&Y+Q8(6c3K2x62J8 zhnWAWj8_$Kivw9njjMhXPQnax!1O`Pg8|CCCj^E=EPCE~HA*J5!(Ekf!`0>yp!i*) z8V@IF^Fno%wSioad`I2wa(PYnCP#f=Mvu_-N&Sz#q9ptCExSk_W1h=dT%;?m5hc>Nc{uFh`m6$>+!`o{w^LcVIFl2a&@rSf?O?=eTsA_Xp5 z8Vz=C(-7fJH3neY7(JTLBM^(p{n||+Mu{UyER4da=FWnmnAZbp7{tU9~;R1Q2H}w8uG^CUE)ZIJ28&rDIdwUBr@Y_UpN(k`HA1u%BA~! z1cj(_V1wfg0qy>K&z`|ed{o7ed#KwYsNkrzF_1ORalxB;Yg)|WIylbeOS4d|VCm~I$I#BG5eOiW5kQE1dlp{HX2xaIZ=;EFNV z=}WGYLK{JUu828KL$}1{$dc+_yF~w1;yy)~sZ;VxnasE^6;4#?r2X^{V$arBS=o3obIZBs{xpVvq7A({Z0>bcr|n1 zWOrem_f`T6(E{n{W@}%D%*4NyBdAPGi0dv#LL^Q%jPGHs5^plI72mKTo2ilUZ|nkj0+2R9EoqkbO~_ZDC7|%W`QHdQWX^Q zRlYCE9YuCDv$Hffc7>d7zVAr;#N*9g4WwL(TZ$z5r2LKAM=K+09D0B0r(z8*obJO$D zGR>#xr#k(Fe#dh|L)QG?sW4GH4s1aNfwmto_0G%6Qj~X%U2o-Va98Xqvy*!Svl<6m zkr$f2)EsY*FT7hy+LZax-h#V(j@sy@_K=1NHpGwDKhDHDdRExSwqaU3m4xOjv|FoF zWQiooZ&rxoaX~>aNFbO6PQ!t>L(Y&atl8*-dL?~T7v9Jg-0Ic8KhCbc5YC_e5geqw*yT@OdHfsMU);_NHwAMW$vV;bxsw{q#axq z00ZLtYrTnyb5Nb5p#qwzhnB^UF`PXtIwBsSPjqk;2@yG`XK{qB=PS|Xq1PkNOQGGL z=fSWU4iC+G8EOWUuB4R+C32=k(lQK^BCmN(^fAd%oCbR}vQVPI_$+OSIgFdh;U&e& zH~i>9CQ0sw*|T5{Z_4HQV}jW>KZGqbjeR!?-}q$iIBe|8rvNegQNV`yQ(lit96q*kheF0$3pS|@QHg~4#$>Z!&j7AZa=AFJNK|-)!S#0GZCIx>9kR8*rvF5 zg=k7wu`z8lcMI?l(%Ve7-44Umpl)|Ity0xbIIxDZf4DZ<96w)*L4j?a&U0sjs_diX zd+pe02%*>rbt`rXDN&7tVYfH-N_+GHd59@+hJhZxYrvx)U>++2@WKD!DyO`XDmPNC z4-2CkurO*ZZCPkGwu+Hq)j!1q??k@8A*kv*`}wFpFGuzX$uf9)!-_K_Y)&yc7!lzf z7)y!0Lenky-2y4+45586J9634UDqMIhouOhq6lQ2q-bb-u39Z-#OpIVo%>|%hK;D( z*1$DClE^H)$5fcTp4usb5I#sBYJ!W1KrFbUv3uW_RjFP}Kw~;)Q zOyYVQ9O8gQ?15!3>^?0)A1@+OO$ecsnPd+j`1Vc)wW)*(kp4(y*xjCwDA z_$&*}<6H!5Om!imnK zyF+{-IvVg6kr#}kPC!XQyL9B^MP)++C&WigF+H`uVErnJ=++141`YtfP(U^62@AQg zXOYo&HW#>xU6H7P7F|FKt(7i`{7we~5+_3ayx7(-C0TUYn4yF1fN^5oOFN=*ErE8! zDUHF-v%nWwdrn1#!SfxaIdZ*57HPpBb%1+=Kv&eK@p5v-BI!iT$%n{;_PIsEeQIOXn4IJo4L{kTvTVR36SCGl_||%Syk z`(om0#9*tFfLxHv#@d#ZYzlFw$4wq|vlm<5G&W~YP`Q~Dh=vsniDr!jH1uFVuo zd|7cm;CGT_((e}%B&q|5o$=A*<4k$_$;~XQ;s)Q+=Jiy@GCnp1O1INW^uVGXf|j8O zs&+quM!se!k+yUwk$j9{_ZLv0I#&Xd;n6$u&xC_+Lu=M(X`Nu(J9<*}4eSIP#yIx zrWTGNsE2>?W9P2g=As3M&@1Hnuo5Vp+%cbThmt+q=0uz9FJXlFL}hrKV|Qja9C0dc zCzQJ@^2?h_V~AX3ZV6s_svlz|^ZdS}7Jnm!0DO%e#HSCD!ah;t2|m0iox~wkJq0bB(M{;_ciT%tL*zm?G!9ALXHv- zh|_5|D&&(&RVdlVQ1QCu&rkA6$@YpPo<6z=nIx*AMR^4o>|p4*FNmN1F_uENG#w$dTbqp zDDXgguF#V}@dP?Uz=d2u5@H8IyH|Xev*Sy7t)*4&^D=cCEuN1L!XF8!y=-j{bJI`X z_x5Z(Y>heo48c-11?FS#JfAunC1Dk63g-9yf^6$O=NjYrEvAI1&-z;+JGeX?__!6W z*zGpu*#i5UMS@%RKiKk_E>(|Sbgi6+4$t;}qeJ+3QkG>S^11<+yiUq(TR3*?@i;SW~%-6;J5vKaAs;7w?VS#pk1quaE zy3fowh`6}#h>D_0lzeK?sU9{e(9#cZh<0}!5oL-UaSB=QHTIu4taMUD zm)U*O3;8xsS>*K;En)xb=eEOj?}G`=mGunGMSqM)-;0;08*`cy?)LiXf*Rj%A;wl8 z{(d(^%BbuIt@@Nhhg5dD>f_!p;ofPc`G2f@fN2n5zOgV7tm zNEnB5t%u3qu&+1D8{@ys1^z4h+5GPe$p5Bq2>^os1e*v$=Lh6hY$B|yb;bDnLeX*k zen{dcMfZd1{x>PQYqIG-P0?Ln27gG={TMO$g`&H5!r!uEFiQDXzx>IL!G@*(G&`m> z7Yp0?!go^>{DegQiPcF=iax1d`0ceI5BDs~<**q(hrZ<3skFWHoHd6h-e=6h&Jk1C zl~wT4dfOEb^jtr=ICC4F`u86w-&08UJqDO0Zi=f*IeivQWZpELjVIxxo8vim%W_m8 zGZ86SqQ&Adsb!YYPs)$4B^1|3t$uI8&Xw{l9#3I1!}jHSGN-Cb{&Q$n3mp}R4T&gK zVwK5Rm!KzNo%FjZ? zdOu5JEj_tF?sDaAuT6Z;n=G2G$H_s&DvbW>(ir+Z0glu3QXOw4`?Me8xe;D;8{NU3 z26L1qnInjgRy`nJ%;mfH__>c2&t zxRGF-xZ^2_QC!#vy??0qqT~Z@{Huz}BNo|=nIh?l=q}*IkjQRR zD^rd3Fi&BAb~;n+dUUdo9 z=)8B|(0+~T>Z`KkmQkZv4!doB{ z!k(1J=Oyw*5nJ9#4Fih@BONxp$!i0DIY>8Ml6xq-!6%lGE5aC-xxS3PBvR;@pd>C! zWn|G$SWo10Ck(iB`n?*s-Ci9JQYcU&{&F~bay&v)GE(=3!JqUjq+sE)5aR7nuHWRC z&BZ*GTr4uM1jLd}=1Ra&YCt*&mL%raf9}_UYwKD`b^b+p?(xU>qo>lZnRaF6lN_+z zP)@CnE@{~{ElC$COf?th=kvO$=QnIYpxI*m^3kE&_M@sMHsLe6rlj^wg&J`bt6V=kWMnx6WeM1!q&^;ke{|HSGn_0 zDn`;}E{*rKlZ-J9FWWje#_r^c!!9sI8E@g-F7eppNnbloPgkdkC^YDS zHlTC6S0y+E+YVy8+1t^=Bj@2kJQ5r0U^fSvdg>)4F%w) zhcVYU=+@gw-wNozq<-xNjC8Rv*9q&co0n^%v9;IjG2fQUjT7&%Y;i{1Z>Hp`6Wz`KJmzQan{}!6J^4_odX&W*3J>=W21k25($OYWh=dr0g9u zFC9}gB6>6jF4mMS8k*$~ansrNOLppce2;LKprWj1NB7v+m0{hNWs+6&W7un5@@;SI zT9@a4*<6;i_jI*`44)$Q&B#c3drn2_lTZEAW&W3+iKd<<&fO}(c(16!+rj&LjsnGR>Yu-LBkDVUkx{2VxY+6A$_E*K=xQKpyy5sbq2~N? zTHca2>(hQ$JDcD_;l)*lqvJ^%FvH%E_y%%tbKjf#7}j#T3L8W_H`WjQ?hVgH)hP_@ z?(@{^c?ZzXQ#$xQ8|)2sM7Vq$oV3u?_N>{ZVAfr>{>YIk2CXA)uL0BG;yGaV(87ZN%|EepP@!}$8npMH=p3Icd z_d~ygXAO(G8emBasuK!UNiCz%d&3~UBEJQ@wwKlepT_X4JFhWkk=f@vl72&w3$n z$DfG49uIA8H`l)yd3G>vu~+>afd>06!SB<}>-Fzvx(R@QKsWbd!uDpnSu6jaNH;;S z?Gzz5%}7{R@M_yd@RjbD?$!_8|6z+o$X`iI|6rUB0K~%`0?3unoz6kuY?w_5Y00 zjq=9$KZ=rrtF0|N;Li*@a9=fGuP&OaY#TNL@*{(U-5vIuv>Ubu=RYI)GwuE{@9=M? z-Pc*{e>&~H4hMgfc7uM*;Qf+zUteS@)Yo40+w2=Q9`-97KeKPx5bB@JzOz*2Z90W; zTlQY0ny5Hr&FnoI6D>%&gWfHKQ*bNJlGS=Na;a^vT$;-YXG~@Zz-#*cRf;c-ke|eB zT+9w1IyZ!ZsL;D`GG8o3m2~4GiVfRB4ls?rGVI>Zd9D^tXxBAL#s6lB?-5-7tNbNa zH41=!v_puH666tXHpqYjhKc-$zMT$ zTF9nK)=pMtm6b1+k?T^3UM|A2Q9h0M$x8U{&bz7e+MC!0iI{N>UkB^x!p4s^9MQ&~?NL;=U%H!|S8+V2WPTkfFoA9X%wel@*6cCB=w%7uSfVIaIDkm);Z`IT8YELW&` z=Ow>OVC&jjoTywSQwC)^oeEa_bl5(QT`4)=@a>yFzAt1Y9FZa)euC3)5n5_UdD(*N zQ1!6VJnbU+U_N;^fH~zMntCUWQDZ6n+l|SH)?0*8rA2^q_P9GoAiyBcP_9IxIU!*mb>lcJ+2Mx?3{{{*4$&(K%f& zSoM?!zbT%`wD^0s%Lb>!?#3SQ+fTH(?NRlw?C6jPq9i(>N_J|owlBQs!?Lj2p?Wm1 zuDkzscH!0A_utUj7l&aReDiMZDV|1yMn{smqdvcgJ`cxCq1<)_4tf6?YCb>PomWb zbve>acP`r5mO1V-vl)q~JDRKSlk65DBlixruLPFiep!3D<@oeIw7eUlo+GQ@j-z8m zvwf-Z<-^-BRE5}<{3?4cJN~+qF1_Y6H_KhW((~5aUG2{tm&0Bxxzp@Zx#7SsfzLR- z4?&hZI;KH2Q`->6OvOv|0h>>%Nx>8A`Eyyh7J}7#i+HDv;TLx^5IXsS-P~GqI8hG; z3D=czy_bOGd3PQ7%cTgqJbKg5ED47*Ig)6N_j_3~RSyOjOqHD#F5sFk z66jVG!DF8uR(?clNH^kyelquQ3

R+U$cTiAFe|vuGE(NVRrr7D2@#Qa3nmJ-@4Eqdy~nVhJJbgeT;MyQc3H zpDTOn%D_@=A$(Mj>=>UT`~HT5EH8yzy_u$6eUnkMU30q<8=;(Y)B@UkUBJ7Ll&5p= z-B(%5X6kk&Cv7)6haJuhDs4`@wVJ-Zf8JD8cD~#8(j?e^%Wn#*-SY5sf|?#HTn?E+ zEyr;mJ)f^~aAl*pjXd9?JWrluE&tv^Xo+DFGmP#a+|J`7vrFy47G7B=;=gOk=J<6V zo%PA-z3LQGifKx#H|U&cHF#>onRO3lYCE5^wJPIhtZBf!au4Q}T9wk(_Q!cI5CuZ2 zIV!Oe&GeHQEMq4F&022H4V4*P?7v%J{8FWH+`u3AS#*+h%D358Gw+seiW4lkTTWIB2xaj8WLsNMR)=yD<@5S$}cLX^bS zY1NboJ}B2p=vph>R2Y?vQ_+1>sHyG8O!G^#Kpul-D3PYdhMANdQKry=oSNUFkH5+ zp1n}Of+0p^q2A+jF{8)m0XoE$C4@L)4SA5X7o(+<85mBhaXH6OvyfpD(9$|j*TcdM$r($)W<@q5+oPUz)E{T-yT~VI!CT)cQ;XNJ61Cuw3$lMH6AqSoe z7VOg(c2o1!b2$dKc&ktS+tKqX;~5>ssNn-QjK&6=CXOn#y(WR!5#05Xo}iRKn&ejQ zJakD6YnjN;)2nCY2|ceIXG=4y)MYLWR|h%Aw#&z4bn+AZh%v z2Etq79rvta$v--8SXQEzcW_D@C%i&W7dXp`i$uWSN*H`5`DR;mi3qM=&A(jYaEb$c zY9<#bLs{>WE4KO>nEy(%(y5*fi1k|Ev6izs<#1)Q+?0vJYEx6w+h<7ADn!z0b-fr zwY3%b`u~yl)=^n*Tl+9dNOzZX*F&dBN(v$=-Ccr62-1yo3kcHPE!`>IUD72X0)96j zp5s1#@9Wv;ynBrEJAdpkVLod(HrF%nb+0wAIj>1P^4W$70^^mGjcMbwVwp+7W{~cs z<$|U2NOJ&#YiBsu`(tvbK5c?F2Pc@if|v0}h2}*e)l(#p@q{lU*w+g0XrcO=RxLCr zZY>z!<4e7JA%VM|8Rl9WTmzxti3ZNA6hYQ3b%)`pRZRX9$fuC&Z>Ypb(|YN#fENkP z!MDuNI8-n>oTNL#?>iEh!1uPprpe~q(}QOXQ&aZb2go)J1sVjQ?HBJ@@h3s?#yWi= zT;=2l#*L3MP-KeTfJ`wf2!vIO%K$<7yZZF{=ntRDwkQokP=S4W8Yw1Q)ZkeaI}cY? zH2Bn>*omEj&tq#c)8CAOt0{mLMnilh^r0xY+^Z5a+fYN#{COuqEJ!S3$%Dg(O3;l6 zV>KU-miZb^7@tSCHy*WNTxzX<$eU|=zB<+~G8R~gNtl|X1;-)0>gN4%7ruLApEkdA z(rXWvs$QCYLsUi3eZH7XU~}AC_OfNy+N{Pju3X(rvrjT1~}ddDeLO>CfF zr{kiKK$B@44Yz;EVp5^TT7PgIJqiPnX2^?Y+u8HufRIS0GewYfnFNeDT$GMG4)0Q% zgfucd^RM3I%2$sS zuxCDFid#NVk>?kJwzwO;TC}ltFWEM~26TtZ!ht(s*GIkH%Jm-lsGH@{n6~Ub_rjqK8lLa%t{gt?S;LSTvbgiggp00v(+4e$a{PhKJGdU`OZ#zX(h3nzj_03kN|EMaqSCl6CubWrq64AZ3-#iKaZ6R^_RlkvZ|8*Ac7mcVGe?m5gl!KO8yD5eh*dakm zI>Hn&T??W}x}4@>6h8EUC{{w;u0k66Rzg2xzSej}C}l|zTm;j~0hlK7 zH}<5`O{#JZRv`mmi63_$td{YJ8SImgA1y$>7k44_g(DUtsy9R)%WJbM$^J?i&83c2 zLpo!lHHDb?I@dc#d*79{1&bGh0opRv4?dk1r8R47Q956+pRGXX|v;jf1)E zQpIbr@Oo~Cz`D2}GXPOZd>$9+P_AENKHMeRE)qtwxuO3R@zm<7)=(0`yRkF5@_|eF z<>gpjzNg;Yq|~rVXr2g=NpIL`Vz>lDeM8)^*t%1oh?h`s*;3}YlrU7Jp7ZV#2Nf0d ziP4;!>N7v{>=$t^d1BU4MB+lbLC`OTwge0H{!{$Dgs_yVK9X z^@1lliVnlG=r#EVK3{F0p7iGXsG#+EIZ6dI(eTV74SDpKyL0bJoJRKM3w2fD&QMbl zl4yIcz~uHqGNLcj-h;`M(e-IXe9mZT)Q`C0JKwm!{Q-R!GQA}R4pA45;qCxAlKO*6 z^GOU$WSiH4kj`2<_aO%9XupY{Zt-u5h;5wMy?tH$ZZP#s>4YcMZ^r+_*Pdl{4}B@# zIx4Nsft_3mctw-ln){a&Ek0*zV@_bbLeHUdKCGQS!%THpgbCtUduUG~ocnM$DXrm| zBDHdY*4cb5-vt5*-!f7x(IG_;zfMF-2Q77HAo?iALJGWakdSvC^B~xhC3^~UvG?{1 z&waGQgy#&|+9u!V@bsj&TNX^b(|Gs_BtCzEaP!hJmIdo8Bc!JsA{2u@qlwOb%_<*1_#DTDC&N z=GY;Hq0XkB-}BVeJ;v26ZgVCV7ZraK5)cQo8rB6)h8qM1yZu-e%ULoLZkBSmb+3a8 zI5fT>hHx;kroKEwZ+&5{f?^pW&8Srx?ZY0TIZei zosR>@=8aihmSpxtrJvK*vK}2aBxNOF?|z+t*}n``273}BCaPv+RrQI& z!nb7`2w{6(=ezT0Nrc6y$1h&mbi0_%mE)=P`hR5#*ovT;WzNR4MltZn8CQdBHv~(H~|fS z?*n+a{+6El%TpM?nia$bB)7SKBjL?{weI(m;9UPg5}f51-Jc*J8Nv>vaan*0gj>tT z1!%ni{ww=)68yXKcJW`D-u*wQ&ER6Amjbc;PR1C-^e?21 z(AdRxYXK7N+7H;D;{DcnyZApHcMvn^H)@eUfat;BGL!#g{TItGdO>e62kO57hJ_6f zX1TTi(QpIrAG&XEowtksTQL7y2L3kH{rhqL3(cV`Jv}zyKNg^K@z$~e@qXpMvOmT7 zt@C#Ae+1^zH?6y}SDm|}fK09BbB7zH5Vqgj(EoN`_~!xtRgvQr;7kBddIk7*do{c3 z23yWw0S8rn*L<2Uin?Dp$GCZ3Wn{j2^0(R4iQard|E{JGUIUF;$yrpbQwntdrx1(?Q_RbR zAA}$~B2g6A3z4ZlAb-r)Itwg3(;LGG=WYK|dsRQu5LAcz+#T4z9p2r_iGkS2JS zd*2&>t28{L!_B*A^jJ<1oCKOQgZUsabdPu10alEI6|4YUW{_o7yyLY)6c%N@G3OF9 zZ;s&p%lg=ilbp1rNx#rJLL9vpLb?h3p938n>%T3npI^2~LPxGSMr74Km9Pp36F$Y@ zeZKU8D2YXc`e`)rYg-JGBYGpI9IQ=e@WV6Nip?36uDYf3nC<4yIxzbCJwg9?TfF(c zZm)|R%(u5i5OCza{c^7liT{pr{C@-E4PyFx1%R7f^83?zvjzUir}ZY7|LVu}2Iape zy@3mcoG%xhfVNm0q&f&o@&Wa5%=4jF) zZ?Lm6m+pzif21mMV0^HNyYHfUu~Iu&u88o;Z0Kdcr?|ZO|-_Z zN|UB?)@RNpIP;bCPBNbP(`F8c5ly}~=m2-vcSxDgDlpfN1rSl>WT`MtK$JPr}c zz|r!$z_^vf?XHFn1Il+g1;wJ6(&cwEQtm9yFS^$Y*MYrm3@D!7%U4!@R>`Ri#kk1Z zoNbnSaw*`Q&;tR%2p|QZBx^GWNh;?`hK-FzTFoC z{%Q+CTuzy?g9G$D;d+g2cJ+F+9PJp(Rtx%3j%I_B7$ltv8Ln;ZDm)U1;&O#!*XJv^ zi)sR>lBFDFqdjWd=H@}PrQrPyqyDZaU<&v8o14xGJZN)inTy_pwz$%45K&oszA%tW z6QE4hEs1$CvExr{N4H6Lut}uxJh?St0pbudr`2L0C}0k1b;@Jua?`R>Rs8(XwEM_6 z*Kgly98XB!1;r>8qs;kgdIfr?Dvd97NyXu=YR9fULu2yaZK(*hck1f3HB~U33TLga z)HteXbv&x6tzBy&Ov@Ez6jZG#*Y})0ZD@@f7N=|$XB@@y31HqP00l12fmMNR4SWp< z%O7CEkEumJPeXo*K)G~(@J@{*8lR*Nqn@ehnttm?Xk^cIS%$DY56D(r@gCA+cxfBM-Vbe|t6$2NL9JJ!Q78u1i>~J4?c-?MaoeA4j?3ySH%r7qr>9|5j z7Qk6m?Q(W53LR+b4~Cm|z7c(}sP0Yq>VV&(LtBl)smLDZ5VTa^$YiLuS!Vx!1CzCx z(D8wf{N*`n9r!mvOy=-Qvkxdr>%At(GbRjCGYP&8g&zoCzQcC^y2DLuOC4A{?f>P- z6$XL%>)otAUdjUx^LQ06%|IM(Zol-7wq$CRx zlnOY9ux?}KocMH$LB$q(h_>f07`ZZFO>~^3QTb-6!e@qzw55{fgoZ#k#c+qY)zv`` zx#mIKar=QvCAh!}{yF0GB zE@C!W-bpsuXecZyDkuV?RtQ4~S(1pSILJ`geaCjrCRVt3f!hyR6_(uld77|+imqL&M=tw_q}zd!NgkB2{MtJyO37J z^Xfdhbh+4}LzpxlGg@dg%(lrY)cm4Xpawt9E6+Ba+A=l@QrWqh$78!Wber9WOj20Y*9;-Lzo3pFDMf&r;O#I`2}F;;zq92 zDFYE?R)9@1S1f@#^p3IbU>R&@LJKuw1JQ*2NNg`R$@*R}S|Z7(g}rt=tIXCyF5Vvg z)-4tV-oxbk$t{vo4i(ZE1ZFVE8(YLS#7`kNC|83kPck4qO_;nss4%V$+dhWf6tgI7 z3uBX}K~-=q44T+HQ37}oN}c{yem{5|@5}1bex`PT`@83Sn2fo32*R2%w5Q-)vRfM& z#N&R}*F;BRP8djPRM%jt%eF^}ehqzg*C9owAVmBT*y882a#jef*!0RR6UZUo z1a=jk39+O}CACQNqG06rtWckfSsLPTPoTg@LcPM;+|r#KAT_~XP@&IZM?kyD;ii5D z^R*QV4(9fMtmT8iS%x9>Fc{M!_#iM-u`U0poJuOIo+dI?Fqoe)q|iembykyC4O_;t zQD1eGMMarE==kzUat9a{6EMD2vUl-^z_SiY7O!!_zgWj%@nda2zO>3%OhU3ZOGREZ z%G1mzd4@suoM_(Gt0@HRb!6g4*m|64!aOa@9MBvkM0ww{YW5sD)B*oc!JNAyu!U_s zA-tbF70s}RXyP@DS`+oNi%+?YBKepmlTt?7GmnP!GF~lfd;1-k)S`tOc`J-vY|K4O zqYL6!xxmYWDceswEJDDe_o1YU6$|B^YzwOqoT{x=vZ1TevllH5>{$UJ*`0x)n9E=7uC!jT6ONb^>lHmRuY+ZZ$s zncfyBcjNY7qU=q^KJC`?&r51&1gIr z)A`(hH`BI+(VirFAVMf(^zcEuYk;8!+143FeoU%Jc|)*hN#MDwph9a*I1v$at!bGq zM79)kb66xM*PBT!uo{)DC&JLeti0geGzso};~%fK+F~FSom!E3q9cp(eVnc143Ko* zK98^?NFw&J9^=mTk@nG ziT6EQa1uv3s=xfnN0qhCiKSI3zLN=EIFLFd#^hedgf70*?$-X?m)bpyI<-RqoknG> zenLxw$+V$X$p_-KQ~X}FE4wQm-ILOYMC}5j`&-sH^9BaRqt*ro$;(`(RA+1TCxON0 zFX+*D9>0BZxmPF4TaUMN;1^nmR5hh`Qgf8P)%P`HDY52DR6oYlXv-mTxBVVVY;4G| zv_H%pXC3`qP};!0(SU$pgVMTk=3~}p82$3|PoBbSralrN4?eovIlkDaYlCbAgR6TY z!uAGbtFMDd#W-}R&{?1Xh4E>CPcmk)g;GR01D}A*Qt>p_6f<+!5r&X{Q`q1-1cjsq zC%G>Jr`pm<=83H8WxNNPLVtG^a~2f(V$~4yK8%A79Lt=cRE10~`xc$K&rH#wv@CjC z>6>u__|ya+9FZ#D7>y8N2`NoHT1pcp9#cvwj=I?5X?vVt$2}~fN0G^N2_$IUIMj5E zvLs}*y`EkmN_fNgn1zXrCM&xD^x|`F>_jzRoHZElZ>2(Z{8e@`;W>}*9juplisxCl zMcY$89@)TTX5T`#$+K8sob6M~DS0E09L||F0z*^AO)PI0-bIoDlFYMclzy0AR_%3= zrI1YJ707P^UZqGGYx?4@MBZa)hbXq<%wmj!G{uU#tOS2UncXC=89}*IJLeZCfvsmB z_S5^f3aX_m@U=dg_Xv%R@f2+r>hIw}7M@#O8i0cPp$g{x<1K0l%gatTpiJ^a`pB|7 zh3pc)vNNoN_k1Sy_GpsY)$xDWLq=fxbqb#VmW72?+dveyGpvim2R{Sacs+22({0d= zQ*Lq<+@?h;EH)Mb-2gR=k2HvmeZpUq!T7KyE!bkrcEO1&~sOUv>y?s(Vw(0%=Wa#oKLk|`T4_sKK z9#IeHQ)uHtg@G;@fjsw0^sR_@n8lT{`9&c|U*>@$f?txS)Tzq5mh{~4%BV*PAH(Tr z&wI+T+{0{AOF9ZXQaZgT8l1Ts2i7J6B#%ZHm*m;9k|{rLtscJ0cTpX3IQ?+A^E$B~ zOW9b2fiMw|otPa)b!$lX?V#3_cIQ)u;(bE;*3YJ=U+??TgT}2?5SCw#$C2SAk%Je( zi>AOYH0vQ%^n+5=d?^{kjYG{>kx0`;$n2uApO+1YWb9iP^fm)QIs^piK8Dbi`k+b+ z`_z6@Z`$%5gG_o)cv|oWqx`8vA4#HkG!a!Z!K&vjXseO9<^)+xbY-l#Vvjs|kH*}; zP%KH*tnHUvJhPHukRpuU=PVjZ49!q9f0EFM7LZZvyLQK}&=~%LG3Lv(24ZFNH0?rR z1Rbpu$Nq3n-W?@w?r-(U~w78Tj#Aa5e z^eZ)jp)!pMt*lkn)Npp_=nT^@vF|i!?hYewFO~??Xm^)BZf98bgZw)5>gzIPK{&yC z1tfIK-9FAC(R|`O7fG0&XZUlHUH!FPmKj9*8a+Ha^in0(X9*3ZQ}@2LX}(%X)I@R` zD90!5QTJDgbjc%M+JT&1weh{+P8c9?e0*x?L;V0EGG!YYYumTZMS&oi7Q&Qkla zcS6ZN&NTC-9l?EeWM<~O=f2(Msqocc(IPU%hS`+F_p{d)gR^9C>U$~`8@_aGejCsn z6}o)3ZAv9ad5J35)1?_V>7dmwkM!lMwqtR9eLI#i`W=(^#T3fSn6KZX$PiT`bDW)P zKJYUYOlRBYVp4Olwr5ay^`Q=9PJpCdWozeC;D+wpz5~MR<0GA;fYWoE{Rs}sZdscT7Yq+t3^!T~&sq#uTMUm|47dIIr$3ii=6t&wE-Zlki`3P1R^)r? ziWShl{*k-7RvW$gfS30#&t3h6r4FEL>C~IQ^Pi_^e$mRt0`y?813Id#Kn=+c3%Z(K z0Qdp>6Jv1eyj}d4G6w&iT8A4tjO%ws6#yy~f0vj0C)pX+U+K7CVG79EvI6R;KP>1< z^ZE+wKh!teI&T;MzmE04z=W~>s)h$(yjTJ4+beSGhXr}Qa;{SBWfiYOWQvh}?I{#$`H<(|A`W5y!76cR!+`#*Xv3|GC z+r|GanBNkkSCt%wPcQO}WR- zA>+z_4IW^xp#$u7oeeNO{HA>5r?QZrM#tYW*f)~|u5V-iTUki&GZjnxDioI_O#vdt z_e3cUB~?u4TH9`PbXp%2L+-Uh8#p3#GZB($Y2EP^owm!g%OwrnZHo5@mCnp zB+z@xeCOL^ay491m72J75Q^HfG0t8njxIdfiQ_Q7co@5?_}bbSu}&}Kt{6IZF-H5P zS~J{Hqn$j;8Owo~$} zx!OG&Pk-_*!mbVO9)~oO9DC+$jK<(Ii&T`yGqSmlPr3_UhwaqM9Bs;2?UG%#KX?rB z73cDs^T9EJ6=b|js@B>T62*Jib=dq~*g~jFqh>|;S1m!$y^8cK$2YA{f+w-kl2u5L zt?jHwFf{87UQ0!k@_zDmXpPjLUBXc2cID?eep#MR3eQ2|I@$73&23VGn=qmaHNvcN z_`y^9rviH)V}xZIL^05#i6a&SfM(86g$`CFNqAcnrYJ9vcFCJxP-l0?F$oFy9G(R|X}zNH(2xkIWpJTSTGh8LJ*xtKK-8 z+hfH`i{V^@8s`eWDYe%wbS7b%t@az*B}cEI3Bb=_#CK8i!XJ$%6GQT}h*?hihS>#z zy~*tW(O5Csio9`yai??WGwR&WL+A3M>!5}gd~EQshGCHzz020~Z3>e1Jq3D?a1;ea z_6@&ziYyDCnH0+$(W4>A9%`4LD^)ZjYQ0vjl1pm5+u?y6C2F&DgyPzT zT?pNltDKC16+=a4Niw>~%f?HliLUtsgu1+)3XC&ov3hVkgVxL4XWg*G9@(;#tHGnLCd z>ip2Er$(fH=j6iRgYNx;vtxfKdc*CnF3z3oa2?MM5yu$EO18~L1j=Ttk14uNSyj~; zi3`jzDbeIHMwT8!Q}fouG%tV6aZwU>!OD9wO^amgokP@uA(ELM67@T`$X5B_7HVOafaDYr8EgSpr>1q*1Uvbj$NGs4T6CW zJ%Sk+zCkXCL7r!0GBF72cv%*ey)4^|mr0+qWh?!*SlRiL32(g~N{_VDruRetGAA5| zW^Zsk0Yg~!O5`zrufq<=mzX}WwmlGH;ExglybMU&!VrzPXAELeokV^X;j0XFyDiVs^#+X==i}Q5*}HS~;!5-I zGeXdEAdBFmN#tYu(orMQ$sJ|snGKccnF9g=u=0v2WHO#{c1B`<4#V(gtYKrNHs_ym zdElXVe6Se}XC*VcOk9vt>+YggC1$C@ewp5=nW+Y!40(D7kJkzvM5s!i!aD3U?5>*a z1u>>7DR38oHlN~+zX*=-z6uv8iq#|qT-NFRj5a7T62EFBig^Hz%rKWgut z0=W`k!mK36m%tiuDZ5Ooki88~s~jlIQ{N zLX1gfPgR4;A;tWN*tIacLy(r>d4a%NQ6fr37#;DQv|K^FNE(^A=uZNX9dETGJLs4h z;qpp5;&>Bi7Vu`FmjK!Pz$VS|c$uXB@|kbCTzB3yMo!UujmHjVK-xb_AKe-sWRxfL zj*);Pxpz@a8`!SsL)ANbmMxm&aq#Xnf>f4v(^4cv5Vf^l7eQXj4)r@qCHjFq_lcD(%Y!e4!_~HRUI4Q^p1gqOwNFlMrl(XB%tX#gb%BV6es(g0CVsflYNt{-ex`hpNT!OGuhq6|*K-kLF zayDa7pRoAm^Hy_uQVFeXBc{6RetpvRtS-Yiot2Z7^`u7c8Qav0DJ18q?RkoAyz;%A z?$QtTG{nws-g{?AaC|Nis-L@^QR~LdCU&Y#os`+h3^Oiv78VdfkMAoq?C4zf_CGg* zqYe7(bza_#f2_S;_jcst9+v8{qw;&Jx@qGe6u2GU{N$iT)Rg_>nHlb`hXtoJNR#W)<}OB)VTtQPXSkKpkOW0o(I2)cdJ8$NB0Z_UP>V5jHK-4UC3 z4vq$XSw6$SyoBRAjHJq&39b>u7XeFgB)e@ed%-^S;=B?j?2`q|1XjPJ*p}eZ>1!(4 zJMI4O^S(6S^I!-fgzv92T3uLaLn97Zc=$lFeTeyd*X9jJ63#vtuG+Lt64BC*+5(*) zxRozuY1GO)aeXxfF7c$~w=E8tZ(EaWrabs5>J*C%FXy(&xmq=H@H*m6v@93o%MOCQ z9SPT2BA#wJ$GkP$bvinNCn>d&_RrJzSA{BUXX8_SVq5T)dm{*%VMReVFCO7 z2|QnK^ZIW+(EUsGFgUUO8b_NaTVHIBx6Zc;<~$@AH43BWlB8WY`FUI@9wlal8agh= z;y4&QN~{VsbXitmd3Ee~aDNFCjOiEj$n}x?>XHidcmX*S&<}cq^>6J<*9Y={M``b` zx;a5W=jQc=>bk7B zmHjz=^xb*8_%8+N{~$^FTT`z=*8}waB;;(rppvd32kPRPfzgHR-z^(J;oU&~hnCG- z=k4PE63GA7&2XF7`E9aIRCQXmI?)dhZSuO@n4`2qWnQ4Tn77yk!Be#4ah z9tUte5%SN5_b-U4YfL!-!Ufo>*lsN#i+h9h9~uX5owtksAIBQV$^S85`TKGG3x4Z1 zewl%3%U5xHZGlmp*M7kMV_XBy+r|G8SpWZa#e!IVC-Z+j;PlT1_b&*p8^8hj5Xkzo z0ZO~q7MOo}?FZ~X0uDHD7ynlP{ERfa)UHJj~GvMEy zw~PN}z-=tejP;Cd9T=YLYwH2?mGvxjZ5WI#8TBm~&9rUxZEP8DM=aYg7}=Vek?Py& zTiDwCR%HGQ4f4Pgo_`R6xH`bH0qvnz2iRN7dOfTfD4GE5&p=&OQe1ubeeu5x)IT$n z=H|4^_FEv`R`FbuNIwQdgIIo0M?XeHgMcmYJ7M%=NHpljlxRQ|<@QscX5#z0?=zi$ zbQXiIM^XR0TYRUJZcfgBmQK1E&wTxz{dL2mLD%=jn-t`fZxB5jRpaisO!(a503tcR=OVgbBpCIt@L-(a{hN($=ni{ zZgbhES=4aH%Qh2d=lM%=4T%i5IrJu0l#XTqIuKPST$MTh#w!3_~ zZJP_Ga1cKFu>7!?r5GLZGD(cCEGng@$EDL>Ek^=x{y>!N8O^IK>49M#CkBmDFU~oA z%|wH=PK75OZT6@zxrH-|#ra=WpG&ul zP)c7l&DAO6eo!9ZsDM9*a_;8!@{5X!vi>r(&d&l3-nm~Ow`dD#P+&jiXe{wEOURITmFpdUvsk*ckoh$Jzc9{O=_DgQ+36c=4S?3u+Xk)$~22Xmiz-GMqk{b2Vcvt)rR%4n#W*b0q~)Ivg;sn%XAQ;d-WuJZ=eL{35$9y+MrGuA+Fk3K z&-7j?p^w}nyV{c|sMi7B-yQ8D$^Y8o$A2l2<# z0ry)Y*hi|$$|}(VGoPDF3`B52GlhyS2{Df^kabN*Q0NXrNAxXhp(G=t?!l+WX!RFM zVh!K5Q{tNehKzi-kD~u$|itVW?{+ZhC z3`_QzsrysbTWePHkH}6hOm=(Qf|H1 z1FzQ#zt=-`Nnhv08+Bif6W>bQ=dAEiK<~4jiVx2wpnL{-7e|eiK5u%$SSSxrM|Voo zMoMl;H1Zm$_xR2?&7EE}B3@P}Odh&)6JEOIV{YXUe+DVx*)2M9NUixGu03Uh z&pvE=*43gI3;uG650j*E0+2J+w!&z@!HE=$*dcXK2qD*jg=7fGM6pm`PS11*A7&m4 z(g}mHqpR`Eq#v77v0kNf{JnSp zZpDLMUrLJCj}R7?4w{4{YE^t4NbQ=x48K`iO?jkjp>AduZ#-K*BZX3<-sOlQBX3r& zGucyBBat8`roe_;otQcOk*#w7M5~%2@9c#WU!Ts*n;ODV+yW0)*2_a_{ zdAEyI)C{qW>5n`d8k_6qPq_zY3f<2hfLDZ{npAtw%xNBNbuFN~Cr>%7dDfE`8{OBb zd-p+#`t5{@OpjLe+a`!Q!<1dG@TUk>_ZxJGcNcSurt=+i_YUaMnMq*%4mph{0?;zlnpi!Mlb zMZI&c*yH&`WJZc6?aepDpiP9&ly9kx{>-JcLrQ+MszuU`v6&zM6InNcPjVMxhNKfZ zj;M`Ab4$#{uO_qBsVhq6i&GMgk9Eu(|Iq_1Gbyi2UroP6<_-jAcguK1hRrW$MH~Ik zQZE9I)q}}C%8(8C-E~rfU(oBokEGMv-e^rxFH`!=EzxxJrWm>SQI|O0e)({ND~rllZLcOy$zX3A!|JS7r7Z~rrV~u} z3}569DT`=w>l5;~L(HPI2nAulbDd}&%_NG_b|fAsxF)W`gv!RvVHMsGy};0k$)p?c zKo>m+%a=kKQaq94Z7po&3Lv8BjN8pY`t@P_=jF?ei7FydAG(t!>e=e&1~2t^CAJ8Y za5vgkMa19kCIqI#=oHDm{tPi7w($|J_Ob&a)P63G$fb9vhG2=kRBeE{{f=gN<+93L z0qcUPCEsy@l+=R1bIqPBe}9v6E3%G}#|Ih81_)i_4L#3#FJEiP>=$npz?)+D;$p z_!ED;+yCK{UJ)m^$22v!O3_2s#`_|+jtEwz8_KqqTxgFicOK!>DelS4c)I4-lArOK zN^*YNHgMRmw2)RgZ+$VM85DoQ`UQJ6pto$Z>fYy8YXg4{MUNyfHJRa_IW_nhua_HJ zeY_*%-jBCuj~OhoQhDqXGjLzYJ@j@kAwr?BxFeX-uJFbsYY&eed4ausOoLsh3(2%yi+(70sV^k|`A|_8s++D9tNZZSyuqk5|2N zq<8P}=kLFNw7s(G7^l9G7Sb|Qr}@Rg)R`~em`H4DHB)~y(+erdY0cC^b5kNTiNbqd zuRcMfCJ_ad^;317Eeiw40)Oq$?&WT!)jl&~Yjr@K)8>1+9%9QNNxCcvK1Y`g2|_C=M@u8fNR?W7 znee$Bv+plF)f?OCCYIm5Iu%6ezKaolVF#X;qfmShT*=@H#|E6Q~Sv-o6^#+EvA; z>(DM=%X5&S!oH(ge&@b1A&pM0Bp1DGD>kXkdfPd`RpErbNrB;>9D*i&`vev}h?oR+ z!K@aBBwd&-xeLvR`BSVNiU1~f6S=4F0Q9*xjG|W~Ok^l!GeI{7FsG4MS6-eTRoV(? z*?y;pKWp9q<>lkEWPz3Y3O#SDW@P7m!@u1BVqw8SUHJe(ZTft8ZWT7&DBB~ezQF!7 zi&f><)+A4dsNiSg0rDGAiGk0m14HFykBj3SB2Jdzu}T7S1Z!Z8)xSyXkI>cj(t2l7E#IC zC=*_X65ayKxZUkQ)c+tMbJu48=IjzveZE=R;#e&vxwy$3%R*{DFjqI;n?{Y!bkJ$f z(CX!vFWO$Ha~1}+pd?>L#kvWLNBjORWYwSR!L7x49*bZ$s%XAqk+N(xO!C7j(5yS- zNj(R;lUC+54KzQvIGjomI;6khr48mCdXyMT+P@WQIC5D6%o@9MZVY<=3(D=s3|rtf z%>rDYe^73JH=*?3M!EfpBKsBP_AA=#S9IO)Qgi2%{?| zgBiG$|FA&n_sR{JpHdLteYZ>h(hS7^0hPq{TltJ1!<7G~UH1F=-(RqI*LVY2$ZNd6 zTVNR2l^ZbsfH&Z~UHV^w_rFkV&;ASQ4j7?!704i<>FbAO2ZsIuZovG6_jljz(*Jb4 z0cE-0N!S5&`=2H_*ndIXT>}pAbU-fair=`lz~+1n?jJ-yzx!^N{MfzZCQ9H1cmrqh3!${F84v_Fu7Xfchc}Ah>tk z>Ga()0}7T`s*G3mr+whodAs;8#pwU!Mfckp<3NkupWh6AMZR6*4zQd+sT2#KaCv2! z0SV0;i2tx1+&XU;|2N@&%bNU&QwIC5I5^DK*3z?30G9i&+-1rBO6)g;d;t6oysU42|IQ#?ZxvVmYhn+GsK3*#y_OBW-M(*`Bp?)T;QtMY&1dG8 z)88jcy7KH2D~g4pr=?I?No#%-3O99PI3uPdnf(I;q_2Y{b z0k0`EHC>?u*F+d5wtSw#ur_2#hIE(6on`q2K84F~fH#M=<~->ZX%o0pX;mv$d+v?p z9i6n#yqMN185~Vpt?H%OIq|RpulDVb4cb2Y=eH~7Sc9A}d$U$R@0i>fkP)e9#^vK$ga*|X1&kTH2>(B8$~TuqDiP&s*G9c zaM&m!R02Y;*+ttKKULU7zHgN7xqWsT7&kbl9+{|B?CK!0dUFReeK#Gkq9I1FJwBOj zl)v1gWZ@d)%?`Kv2JzgGhA`vUO)B}EQhEKD=ug}mt6b_IANV0b9=gk>uoS>Bz_l0Q zYtAv(ijbf8_H2o?sSmy*th*?TqpkVG8>xl``GDF+-~J6D7_Zy-%R5Ns+-PbG~X`Vu9FB7%`VhEUeyq6?7?#^B$D z*Gk2^(_?!74rcBlv)?)E{0c&dXp%eDmK}e79DPIX#GA2gZ`b4b&-~7C^)_zb#_6eo zEk2(tuUIy$n8CPs^BESz7M@ko3injL#Sz1F4XRvzGgS1t^UEW*ZgHiY@`Lx&Vlm zy)U|?K|VFB4*pNL&z^(BX^9!7f=~OQEfA_8#*qz^j`j0+@T`kkolHKe40q5lO65mr z;6a;pJ^2O?{kh%oX?>kVBO%lj>%8z(rKAenJCw*YO<@c=dPl$k@{v+C@S&weKboLb!ORW+d!`e4OR_K#lD0Wtn z6ulvn5;DdMJET>K_2CX^o3w*ry)aKv?uNIVD663>$l`*0Iv2GpG2s>vHU-X}T(N6j zqGv;{RV>Mcw3kdh^)rg`n{c+Cb4W)y?NFeKk2vX#8HJbFBft6Lh{x0JJtIGZsPpuN zLfHixJ0ep*fv2yd)t&6DT^~u`r)F$s+hjYvD*Si8+RcPjg-it2STtb|AuzpCCJ2rc z>WIYYFd4(cp3*2+=b1?!wJ0~9V&_0FQ)JM{&r4uV=s;I({k=~CCD3`j2j$@x+c=%eqOFbvq@8wiwLl>cuYD)!;W;_%~ zF|TqiFnK4C_CiXQ4f)=s#NJC0KSpN1JHZhWq`uys_op*x8fqXh$K_#>pvda+f8q zT=@$0%XpZ$4LFRTE!uax3zGzmEiT>d%x0u(IjP{dyM7?%f0j?cSJ5y&@CsXovA-e6 zLNzdxofCh*@cm)zUId~{0@k>5Z{>3rR$6tZ^R2aBRGm9CE=VOwpnka)cUv%$j{CjL z`pV#wEs!Kn%)8Yzvjz1GHnjs#^ggV|@iV#TL}cBA=4EPIg+Ra1!3AT?p;8+ynr72p z)^}>P@V2NZPv#?|SFT`xX*Q%Vn#LF}%`u%;`kAuNYIbK&G*aK+IR4e)dXVE>1_y4j zNwcB&RC5N$#^ri19QQzs?@PaEf(v)a*taj>UYvUxa`05fdNt&N&5=D%=PLJw;B=ZY z5EOwEP}jjtt?iDpL9eY9!-IdQAqBM?wM;%RzUbu{DHH>f+gB_>??;+UBE*m5*=M}Q z=nHP$XEa8Eh@W7P=Ev;DP6Iate3v7@ci9Demz%(Mxm5a%qy7l_-CM}=&zuh<{Cu<5 zwF+#a+wV>kkXJ@MeVBN^fZExvM3&<11`L;nC9hk~C!;rgglO;P4yL8S^=vF^R=*~H z>6RVssgXbqw4P!mbHc7AqQDT{;)pboU3Z!b1!oisoiacdT_=LF>%T-`6;{q%Vryw? za064t+*4dXg|8&h)r$}>jW2tHAM_4|T>=fRm?iX4GHx*ke-`CNW@H-AAou=zk0%0{ z1Jks7p{nAF&Und4b`GONcA!O{?Y;JUn7v|Qh`;Wt zzbH)iD608BOxdT;C8#kT&j`B(OoLan!m&h_Gu-rYYN!u&FE=>DN|0XUt|^6vNOhmP zyxTe+KF)kB!1YAVVnl3e=o7Zxh9_*Zp)IW^FE=bRF#*g89|RzDn{4n zNKPC3B=2V)`lP;|kqP2*9SU0L1s zyqxs8=Zr=L+whVQ%cR74_J@7?(_Vw|$2FHmw0Jwsb1st#>PGvstW%xA*=@-(6Gg|H zwO_e+6Z(oj2~H&v@#=!CSa*FrQXx_Gq+3wfkub*H-NaB@e4EC1^xo~uV>F2)x^Nfn z$tyJC2?X{uz=hF<;rxH(y#-hm-P#7MfRfS;0wNO9n-=L35s*&lZt3on29<6lq`RcM zrIAhn>2COEZ^So_=RfcFp8q=6f4=YHf;Ib@HN&1~o>^U@(PwLudyBKWg%=c^0u)?rs@2HE2kh$`j@vE^vXxDYNsKw4$|g?CEmNUO zPpA_$tE9BG>+~A()mpQ%-rJML5OQ&-C~#FQZH9RGy&71iKi-}ZrY8<%MNz3aHwZi` z_9EKS3_Kz**_u~cjS~xGbB+6?DKh1B@9Qm070=rAH+vV`gX%C>8Z$PE_cR=z@q1sa zXHZJNTWWSN5jAW1O1~i)9Sxe$ely(dnpk<1086eui#nBpG?YG8#eM#zDY$b32X|8d zrLCWeACKo<{Z_Ikp&<_@T|lb<_rjaF`tK$a1Z!dS{qYk|9>E2d#Fd2*s!C=}ioEfV zJN1&FFPYsW8R`+UzHhS^PiFv*s@~&&X!@C)_)GxBnE!5|^)2u74-d}{)<;{Mto1%h zG@!4aZl;AfEAdRGpZPFj)}eBme3qT`MToBYa@(AOWv^>NOahwjzMV-=a{9A7ybKmk z=Ih5NVzUr!jC52*I69ArQVExwP`1eR59~&ficv7s^;#1jp7$L_#B0#omTn8w8ko-t zmYxe(aUJc)bip6i#u1utO^iX!K2CZ1W{ebJEuDWnk^%a}X_J8n>Z8TjDWL^rExSK0 zy)XRZ@H&vYOJKVf)Izl@i^=FF;!6bKjE``04X68OWo|9pSMgjfm+RH}yj}FQ8tSeG zG$*Gg#TQQV%{A-ITn_VzPhLwVRYWCK=u1pee>-x0afv8vLt*j@LK3p71uu2Mgd`hK z1m;IENXFk4z4@;qB-y|*g+LI;($N=R{_8vx*c$WpRi`?~(IW*(5< zg$<~f!vweo-?Xgk0G|4^>^`GNjo!5Efd`zVL*SWQWKCW>d#Qs zUndfNK?Otf29zxV>y7oM1?>A;pMN5QZ-h6U|JN!R40ruqOa2A_%Lw3>tbo;mv)TP@ z0n3KSf%XrUd?UQ+{9mDD5lc-A16gxpU9%VF+Q!!g4Y>OM6@(X3IP7mKo9!3mFGPPp zgb74{H!Tpqd9Bw!2U~&f3^=$Gd}n~p|Lc|gZ*UGktouKPvoNw=b38yu3xw+dS}=vi z2*|GzmY)_IsR7c zlo3c+@aIwIhC#lbHUBPy3}IFO;|wxn9s4T=neEREGGx&QFv7qy20bqtGBmOKs||@MN_lY&(s0a@b_=4VQ|=p%G2(Q+jWjwKs@T zLTG~WUnb>K^OR^iV~r8(dKFrVyO>;CV>FhdTDl^MCEl@fG{N%7oj1?Y+n%1C*tLu< zYj`k}mAw&ng^8?(lHK5?i;@r;7StQ|G`47xEoC3N*p;@9qeR`vz`+xzn$w~W;un|;Txla*JP zoPXht_uw$2vGDfcH>-?IJPlFk^CVrTDHJ;%Gha5l*U9>rSLc$)rgtuz)V#jVG`P88 z(!0UZ>38v49C}`~c$bqs)s&WD>m0a6$j>8Eq+eH%G|jyfQiR3?*vn1@j*tf7%$bZ@*nui-7ICryg@s2bfcBM2i8rMBvohl_@uN>bd} z6CK8a@3Hn|c@4^8qIM7S77h}w!BC7e^g%%CZ_dKMHuS9I>6m>bjE#J$YSYTbd)rmI`dtCJx3n_h=M0x9W?0Ch% z3W6$$@TK!ZR5)q3a+I~)>TaP7NIS;un?PJ|hd2cUGl@-D7cv!$3hg5?gL?tQ=Fj zsM5SreM;4q&C(w z9+#BJ@ctV!jFy5c9!elFP;Ue4xx0?!Zou%Nu#$X(!3_Zf9Uv{8;|q5M#mxgefTw8 z;a+L}S(%xnl||Ni-xlap{`uwtQN?yG-3U^ld;Lc5p7}Sc-f2QPGhXB+`=(L#OkAD4 zo9-3%GwYXMb&zf4a}nqt7HZVl*u00Q{@~#es2pHcq!~U)(G_?uWl0PFXk1u~+fs1l z)wajiY08Nc)nzUztS6PN7E6?$&e54}zuRR@N^Pj2fa(@UPX|%79&HQb^QU`8i|WUO zks9Ela(TQRV9-L{%s|oLV|^^}co1H?xg)GIhvAfrDfJ;`0?C_hQbD0=rquRAvdEPT zkIY%ml2#&-A?8D;nIKZ@jrG&GBUIbc3Ln!?rlYe|>ueQuCcaqsuYK?5eDrj1zRT!8 zD|~iuN5^iD%t`;d$(Fpv-r93ot4aIMje0!RKH_|NTJ|>in>7e=Q@I5fzM(x?pUB@8 zDeNDz4)?!#>9qH#6!CO8>HD#5aA_KAZ{}nW z(poi#B^ZiplowGEn?41Ov{8u zB@e=(>W$Pr13)yqVj~~O`!P2ugeBh#3tOZ;Bkjn|+|tf}#WAUXePrl!Hso62=3>=v z*W;z_GE?aEoE%T5oTz+5D*)|KhZ^%s=z9WuA?Oa(rNjD2f=By061WyCwhJIki!gG2 zg1Qd5QYyvPP;cG)7{kqc<8w%eq)agug7FMxLT}L&HTOmJ1Vv;y8!%#o-4V)g@Vq)o zDVYW(p`{z3-4a1wS%*DkQ#m*nUQO9wniLb+k@KQZ%db4eUY+TA7*0iFS4s+a!p)bk z7_sq8@(iGYWH$(;)I5(RNka1F~~-7-LJ7Zh=Q9xJr72e;D6Pf=Bbt%XQHyW-*M`xxTuC1 zYe+zQ(r)qAx+*2!7p_yo#gRB9e|$rM`lnwE=(SwQ_^iS(>8ZpK&%8AT!I=Mn7VzMX>Tv8&AD0g)ModOmnU z{0l*WjueA$P0|eUbNdG0P6qNbT`;E`S~Pstjpc6S6JIwa=IomddK{LZj?;@t;}y0` z<;8(%g72x2GE}Z?a*6c70xphQGe5toR(I+>OP~!U_NH&AEA>+@jA8h7Ka=&5VDqWq z!A|n`C}^v)8kn{9aF-6bI@6A08m098e5Z~94^BUha^&zLwG)k)W-{&CO&l`oY;vE^ ze#+U-Jf1d1k#sulEz7Wx8;LXxU2N86=nu~4eIn3U!n=yLq9Bgaw&YTKDPm7t2S!hfI}RA8;H)li`jtgf9K6b+Sw5019mIY zS)^`jH&46E zPCn+Z!u}y6I1cz^N2y<4@Z1v=!C`n4!?&MabN|xWgjdEKJvpn52Pt{s7PZ^7BjISJ zv=#0l9MNM$-22BB=a>85%2Mes;=`!+Ue=K?KE-55zxPFYwyNMxp`&_0E+%8a%fN#J zN>JomDhi2rOuAYvFF4-hXr&UqMW51Xdi?yY!&5_X8cW*F?tP4ow;Xcn);7#Cm&k&TP+SbG{z2%7>v~N`}7LGh8!kMkghB;@py&j3UiXD5Fg{IFlfM z`XT6~)H^y-A$fC({~pdmyQeCjj`9%}<OvGR@wNo-TFn>?b;Qac&@P2OJ zn8aqk_k&YI4bCd}a%sJSds!onpH0|8gEuBq;3sMa*G>gAIfDx6tGYFv=#cvvJnh9F zYTirj>|Dz+t&eByP|n8kh~d<-6Us?_%dC;ht9J6`Q4qNi79G7=&LA zU}|vCyYq}Z1-?jX3ud{aENIWbrPaZb9=>OPu-?J?!LbA8vinwx&0#N1w%yY? z0=-rx@5^v%z3<`q(Ri@gpI9TQ^#bVQ)^L~X@n>GtgbywcON)6tG7tO#3w`0-M$wCgx$yofk793&^j5hB& zlS1V890FR~NEnu-g1*X0Ej(n;a;B4fM#$Z~bUER|BA$_Y_4?wb@(ZJ7`y^sOp`lZ% z8dAquqfdn?h4)ibBWi_fOX;O&8??4@n+Tz>(~V%?&H6;KR_5Z}B)_6@%X7qUoIEOQ zw@7xAo+KIpL5@>5dePpM>>R;)*Bo`@HQXt0ft5s;7ft~^rvi2LnU-URVBx2Ml=YMp zu{(zuIpR>8ISYm53wMGMu2#f+s$=K2w9qpskdZ!y`kz^6KV-@)iU%s%Nz8uEkMDA8 z4$L@a+yli8mD-iL)T%ErD}Hh7tRvvEHjv)^l|n4MbwDF~ zC32hCJ1?q*_;_zZQujS3_sU~uw=QiSB$ctitKM2gI!;x49Ii847Y-A7#4A`7m>mZy ze&GV{vs#s_4(_ucE~lOIiTwJ`J|2C5;Qf4j+Ol_Hr}Zr%-XTM8dNsyQ?^{BGgF?^e zZ2jpI-$+0yb)9AO+XY z7O-lF{Lj{XBfRPS-=T0#YXdoJLldhX&I^Bm=>`2eg*DlK!Sq5D2UsXXaW^es)Yl6A zlU3gcZ#w_))$+eV@v{Gl;sv6kSiwUE;1%+-1w#D5OaLp;UMup)*l{Dg>HHtn@^x6* zU!i3|kV;H{leA+06)g+I-ZBI6XJAV9XA2}Q1ScG22HHO=>4)&9^M6!Hf7e&(pYq^; zsbnO$vf$sI&)9!K%R&?jIB$Rer8D2OK!U_;h5zaO;YN7V`TvB%!34|SweVlivS1xD zfs=*+ck*WoW(&dcpG4rzFz`co)A_$b;eYgDQqVLp(Y5~J$;8P1m*%(M^H%@EcQ*E4 z5wj4L13n%QmH%jg5VA`q4TXu&CPz_;ShR(>PA>HL30<^RTF zko^~nLC9DEWD5pYt6;imfeQ5yInZ8f_4i{rAiU}PU!n3pcviFgl}rPmUu2d3%bwNj zzgPoaD;bzDAxi$y0vVvLmHdl06eeKjP3Ql$O8z%;jd1*82?zpm9e^zuJW%{>!Nv-f z|Jjmngg2f4`;^T3m#`xs*T>(U6ghse0=!l-FeyTm{G$aMD@4hEvg8}#P3Ql$O8&>3 zA%A(e;P}-F5?D@yz%@a@!523zFm!-d)ZkI!T8}ql@(rLG6Kgvqrf zg1zuS09XL{dO@~syz4+f^uvwp#=8y#0Ax2Zh_@Kzh#L<+5CHJp?7i{e0|Aw>e#m}S zMg#q4;V_o`~Tnr2w41YH{r$y@Mlekf9(U9Agdl2 z&w%Q7B-6d1TvaI;EKKRLB1P#VjlfU*oVW;obYII--#YZ-Fd?TpPvvpV zQNCzOc3BteQM1+eP+p&cT}?I@-kPbxv3fs|=n95UqkFzCBe|$C^`;a|5dGHJwIkM0wjMH@A-dle)#U|1ePBy`_pNkSP_;4ZF zZZI>!XZ-8yu!9vow(HPn@Edu-XE#ur9j>Be4~PPOEDKY4&S|i>d0+9vMRN?o9l8pr{80hb!78&*-`zt`>l6A z-8rbsULqnME5|$a0~vi6j9(OD-#5f7WMbIE+Ebf71e4k6uj4N+hd%D;9?YP=_YF>A zN}J)=7w!551qd-e@M05qf>{9A|3}m(2vWY}dJzhFxc`$3;QvcNCJ0hs<&TTwn}O{5 z(f_*x8RX&oj}K%&s>J-3ati#a@sESV?{aSa%260R`u=1q!5|Hz062@4l{HX1$P~do z-c$izR#u^`MrdafI)$h`?fFOk8Yn!N75+r|<3R5G7gZN-2U^1xTP`-6m1mnZ zeSB?%_oF2;tUBUZ>?B-Q3I-~DUM#oc4)#+k+h~7M%BY=7c6_4sIM3;1p^Ld8PM+Il zaJsyDu$nHX{E#btdJ@~70XAW?=fm596EU3LSS3}xgr^#(izLRff;#b~8d)rLCL`wq z492^YmGWo1q-%|-LPCf*I9R@4kIKi7^l6NSJ{S3X^jR9z4}PU88_untZqu529#K-+ zvL~WLCys}Qj}~)ew(FhaX-6(BM30A2u-+5R7j&n%(1f&0XJO2OHQ-}Wxe`p5mLW}? zPmwiigaosvxJJ_$E_VC0W}4z%g8FHl%I?rRi~$FFL?#SkTD3I3Erpoat#=t?9Eu3B zdj;RO1$8%{78pPULSYtptylIcD5O@;&#s1T6*SF>)Rens)r!w7t;{JdRCMehK2REa zoH^O(wO6O{5XhC?`VRs6`y9(BKykMVU z&f!|eUcx6nJg#0kpumhq#AZmobE=(8sg8&(MjiE5*|NeJ=~Z0|2rVHm7^a_8lje~& zl={BUEn2*jXs&Rh%goA+_e&rcoxPzB8HA|EB?qOP<0HXx8a~h(!z_Gc2~5%`Zdn5% zG@iFfNuX9S{AN|!``yuSZ@21O6Yw4R4;tiyxUrr?HIlko3qoP|Vr{e~BAj<;&AK77&rrhxTUC&ura zT9wP%`jUz%g}&t16kak|?T=e_xCX6cLtkIR!NR^J5eWQIM3z>;LdM(X&cCk(?d57~pHW^fqf)80UHW64`tyJtYPTC5()%|gvf_9f%+p}`T6+&ZAGSaD;+4KS*p0+rsdkvqKu$%lAP~Iw% zoRiG*5*ZL9joy8$qkQi;6US{hJ{E!7p0_4*)$HSaCqef8$BlvgTPc2Uj>%Uc} zpz2S5!1u3N_OHopo+i}Vg3+Sqj$-hTCW7<5x-E%Lp5-?y*%wTcCc*t2V zxz0IevU;npoV}_wBRLWz_BLq{Yi4=iWfhaP$6F%o!#z);vh}n;E)%2E<$53|S$HZ* z^iWykCd2V&l$%U40{z+4(UY-)v-L{oB`a2y`amxM8*A9-dixH>&pvo!S!`}SPG|oUXf5}L_P!cZf2-Mm$b2^(c_qvmu|?eWp? z-V&%=$#MvMym2QLLqKTEe2*>tTgmj#QuMEGe zI=jP+2ScDh#mW^+5*eEJJchYG2q-<`PEcXX1$6|QB!PFPe@B}AxR3uKyH*w6@?5=o z4taD=x@`Y?L!F-~58hN$*@dPh%9%?S)OLTu1Cor$R}FW@sSdtkFi?HbvEsiySrc-f z`*?L(ym;4D--8kvdW57p;I>{+0GxpS9UfU5GQP;sp+=uH^bFUrvT1%Tk-A_v6koF9 z5~wH-yYf8#axv4<88Z9Y+2p#R%Mwu!&_Sj9>qV90m&NoH_LQ?E$U_jSb?3p zJ=*P3#p+hFHTe9i!O-Rwo&|UBM4q(YNh^BTW8i-lVlsFTC!%qDX(T^xcE{Hej+#$0 zV%Ywk_pCZEoZ}s+_T~?F;XE9x???rQxC*7;We>WCDo)GGJhGsfIZ6YMBi*o;X6%b` zs+Y;y2tR)UPiLCtNn%3@vq~o;dOuGt0l71e4R@0-49bSoRIkFXrvKi(LR_7OCum;v zsEB6RaF*RvM&Dm1E3dOp4_RK0y%^vtjb_x=!^Uz_C;jGZajEZv+*z8rMDG8=``qFC zevCm`GE=j(dALNwWVJwpxE2yJ?=BSP#EPBRM+?9I~TCP(V)MATh(T0W0_ijiElJEeHetI;a3nm({|tU z6?as<3M?W#r=o$U0luDB`38-n0CtpYKK_`yZs0I_X0nmgk>#8CdrIWEO-ov+L+B~* zz0z_8-3tk)M{J*cvrMR?4Xv2X{stf2ay9{bIZkr&ZeGn?z!mFN@p$0NBPZbu33qRe z*%bm#hv!rW{9m3uQp)@A9PRm`WtO~Z$)4<{fE6R2;_hN^{$^>3T3vs93~CZ5AI7V} zd~pr`Sojot0{$U?TEe?uNnye`U^3-31A7ostg*f>`jts*-fKfDl@*h7%zQm(>9Z;G zX+MsI_wu=DjnF&}iIkL|b_uOqP||x09Jbt#U0TE$0nxXh;7u}xl%=7kjS!BVtod)9 zMm}oeed~M{AxeA4{Igou(ddTZr2g%-S95XiC7&eO^W|?}wRm7ZrcQy+q`>08b#>g{ zfoSTdhtr)&NljOtOeGa&?iZZIP1h}^TpbZ121ATukAxBSJ;3?ixIF%YT{L$0v%r$- z2U}Dsf+s3)?%YsQ8p!AmJ_+sfDe>YMy-3>W64}jI!s^52F|=LCx`*%@t%dWgQ-#pu z!cpTXi39Bm35@Ap9XK-VUX#q!V0;t`Za|w0x2h0 zD=9`#JZjtC)A2rjaNkIb;_cC=Rj71})z?`2X=>w5c7=|xFJ$Mv1nQ&Wi`-B!(r3PF zu4&UrXJCI#Fo<9Z^Ab7hxsaqzJQQHcC%A}%M@(02__%f0<9XgjK%pGV#%+CSsNFr< z-XRc)e$K?*&LN%L&KZ#*(S^J2b9)wq{xo0JHGl525Rr97G-mQNBhgH8vd-q4kAt1> zKGtDjI~O?jJ;)b0I3u9l4KbRqUN}Ba(+}CoGat`>$+<+46VH=hHAM4hgjan`tfm3a zKC0;KFi2F~tG2@PxDMt!%yvmjq-2je?L7KM9oqbZlS;Y!aw*1XWo<}kjs-F8nv;26 zEbo+;;PwTWG%@qj4RSG&i*@0~aGnTeSw4CPN4&k`!8pc!3i?cp z*8!KX_*f^lX0Kb!-%}f(*luGb6FHkSsB&}lu`0T2)LJ=ROr!Kfg!h#YnYrlJbf5OSb!-WB0|Y z**B*jd8*UH*?G7mewP&PnjRxkSjJbt+0M4H@!1wvd3Em!YNXeR;umY*pLHU^?ypQt z%s&^uKZ~<~vsm8%HP?BCA&cQ(t-*f3-g+fd9Wudyx_*L1L*K$zbX;}I(_?m^q8tIcYoSQ7X0G8{x7&5Sq&D21MY z=)ZpfD#TrEh)wT2G5M6WxVKQYyk;09KYUbmBE@Fz6QNk+Wj0bZedwb?2My0vqwwv5I5o(% z$eWw(8`!l7cYPhaqECrV->V{;Z8tk(j+);r(gMkn^b3&2CeSnya?4p@`k8`}SZ zw2#`{;W(@Os(#nru5_f=q3$SLxvhdz>}@Hg7s_fN2&++VZJ zG|n_kHeBhck6XaI-@D>(Hy?>hje9tmvK-<{cy53BFw{+_qjdJk;YdokFD`UYisZw~ zRi^rkB_zde-nL8Yfj*Du+p3NX+ZvhXf=S0!8r#$4NDuw1cey8a)Sllru6zmVi(Yi- z*s?QIVJlcXK@|5~GW(Ue+<2b==EBUv^qaN(ql<*FxtX<~u9dc>p@p@%<+aTKA_+}X zz@1oLM4Derh+4+b#8{J--`qs!=YC;LQ$rI65=zJ}67VjFiw3>0iKf04$+ZIu_|*LT z=JtRKF)i4gl@^>XfRPcvgE@d2s@I^osI{hvp*EkHzKJf$HNnJZr43XECgEVY{s{hV z;Lo(69|8eQi)Xrq`UXH3=4%%M8Eaird6FM4ir^2=Za#p&0q_Lq0;vliV1@MWGiLuI z&J6Ajxxzmp6c7==rj;&u|36iVp{13zfPtnZ2@?o%zzfYEp8>}4r`mqgH1LgXkaQAy zAv0}r9YZsH5_$zgGd?pb!y5tQKm|jfsxmlXI0%w#9sIq)Kj3^(H{0Nr2@)U=$N}h` z8Ms^)Ab1_@A;=0Y3jzd)vqIqa-ydVi)Lk^j*c{s>nEDyJ#gbzB}Izi#BP9l%?6=@cak7c{d(dn-sf?`qhr8y5G5 zH1-3K4p~@bM>JcHk~TtKE?b#&VF2&DeD33jmwxO+RLHTfsmDtPZ7v=3Hkx=go?h); zT|JfTwL3gY*eV*S9yxP0ZX-KBfhUj5l9BJvd6T+3@A(-`h#p%gm?|cLO@!eD-cuu0 zGId(%OLg>qo~iY44$qRGi^aFTHa8-2+mACDu=u9s$iinwAwvjLnXCI=a@$NXi@}`8 z%>b6&*4q3rs{7ST<@3oPOD9FX3NF@192^njZ*kQL%!w5hBh+<>tCMp+8`#FUw8wi! z3{*b)=&&T@({FoLuT;FQ9aO4&$S9;M^bw2sls<5yMfdQjlY^m}X8-!ZWO+kU1w>1))C>C!#&!Hb zt$>uD(ETzS_VL2Z1v6v2HPT7FukFSM@=@^bOQSWFULqQoJ}Y=zNoEc$#*#?0@8pXi zZS+FDS~GXz+$JopfqQktqZRgh$LYByK6jYG;(M5HpY_&Lk(UkW-y%h2;(8S?P( zK3L%CxSnL&d2~$kT2Pv+KD9o55|zKb@HPJ^oObc{i(Kn_**>{+r^TCw{mT_zrqd%K zeCi-B-bNW;g1s2iCIVc{t$HGBerNL)s5yMW1Rpru%**zCiAitI$;NN|k8KSaabsop zgmpAid>_{P8ota?n@cnmiMQ6kyB)FOP}}Ml-}}{J(mhSODA;ory621B!Lu4Qg2<$# z7q`Z=>d8Kyl6>Lh%;kKFXJ-FyWO9I$?>*?m4sRtRBuUmvc7fs&fRcjGPh#^G%w}l3 z-bB8Alz;iU1w_}kM6kv(M#gvcW!zx+eIPnY+%AG`#MJu1p5HV_*HTj(4$9E+mm#)P z?DjI0d1{R39H(6&hz>K^`X>QLmyUu&)ukr+r`$6o-*b7o-Y2jZVoM`A-Hk6uv=#88 z7_(JzL!OrBM{Ig2-+yH{bCoT4CVdg#~VB& zHXd6cTDEjJg<0)O9EIXqc*%4?$s@nhin?o#r>Jd9vS68`t!x+US1Fd)9c8*zxvZ|# z=-2*rHPC7ZiCbrHcdtnINq(+-O_(|~9?OU@zoI#FY6Nv>7kZ}$- z!kvl3Rk8hpR`|0IEATPMEY-906wLO#hqJWsJ=JG?I0uA0hjStM!5Br-WH`mMU6WaH z3F#ANOgiP{xY7D-gaKGs(X`AI#z*}nG&ndXNo_Q_W= zm0G30_vJF?j_Su8Jl`b=nH!w8E_|cupGYSR!d-qvKTV>Ne@Z^>XkcU=7p%Cl*1^X1 zf+V{dLlrx^vCc1@czIZnt)!O(yOb_@Y96n1T6Vn07VZw0T#(+B%d7ni2~02Uk`wX6 zms^kIi$$i@QvD7&W@RWkb@^=zcW@@N0yiQg)8Ys663RETmyIcO4ee!igDa5lf6j5O zeqgtcRZs+9y{Y{jixG5vq&EuzWC}3l>@FTL@#)O;@-KGB3!7n zkYpZRA^6k6_$#+n(3 zpI(i8!?s^p9pz{C^{7haErk&qJE+>hQ$Et~T#!8<%BG}63K1>v{~9v0NFbcs5jLt% z^Zn|Q@I*wu;OgL8RNSJj_`9~qnfKX`R8H*T)_S+MbTm3KJDQs5O1}V*O8&y{K z2(c%0R@Da0W$* zkzTYQR_6?$haALXmoSiGB*952a9|K!`Xd_uu# zHx)(8M)i$@uEr_YP{~+wuPB+b`%Yh=g*VH>-uy#f;!+8;>O$xmEKtpTSBiP+^_g3z zo^m{O290lpc41Z zJ4@<^Dke(#!WJ7K-7PIBk(WDlTY%EiZ6pc<`igMh-2+Aj8ZA6BdcXN%`| z!QR?VI2fvZRHyBI-lbe%-z{RWf${~wAQpIwNnBv8w^mgqJf%3ZRQblyFfz35KbUW@ zx`1*XH4(GGOiYIEcRYvoDjm>xej8LaY>lnlvoF<1mp(1GRi$cITAhW{G*nRQ(gc?b z9jato+2Z^)b3grAc1ML1wFLCa&jln3 zl+c?@%SiV|+!-8hafVk{rOgmEr*$)Kairrs8l4$ZHoi!tykM$TG2Ulf<8+iS$lXaG z;R+nUuhaE5OPdxgx&MURL4XRtwVNWR4^!{pBN;KK%HKL!-Ca=;on@`?eEOn}@4If? z9bLgpF{Doam&4so0=u|*8mLVOS{Sv@x>G}>#u{K39F0gqKalad};9lgNt}cMr?Zxqyf2sb5y_Eaoa`5admb+g%hmZ?wO|Abirf zEqkoAo~#8US&}d8CnYC8QWlcWNc%--&-3{b!QC^JD1XDC$FO4qx86yt`I({D+a!j= zv_eNi&rq2wn5$NLAj}O$E|g4rSw;@SC7vDZ#(mK2Vk~)tM)*Oq?)DzXO8RR%HGwU0 z-^1P~=hM?o=hS$fX?69ySk*iGnF<9=!z$Euxja^ZUHT|ENJFP6)GspX>AuyeQ=M%y zy65CSAUSY%)69ZpuojgZfUA4^`8HB5GYFxvLhP#B{neIU_uVS#_uQVn+amWKGop^q zs$yj;ihY8DM;ef1FR1f1*FN<$!CEkIaD^6Rj^-Z0iE)E7(jn%pg}XmS*o{MMw^@9b z%6FLG+ukp6-hf83`@_the`?)k^jD2lSa}b$)PzJcCQ3h!H~k+CTaAcIdcP9$#|$cO zbsW}bC(gl`F~KzGEbV4BDaejy^cocZ=bJkY-+@B5KR!>#=w;6(cDh@k*=J|1z9w}_^T^P|F+LV_YEo=lx;fxd zx>S4{KGu}eai^dNn|2fJO9)7}o?`_;4u2^11d03OIFaUPqSTn2Ks7ZKq0vJgsiXcV zOPhDc2*^FbtG&7tyA96kc~Jzxj(7Rv$tzYtYoZ@Wyzml_z6DUBJNFczyvzF{a>`kl zOwq)|R{*n#X1J3m=peT`Fhw_*h;3yYartSNR8T7!v1t`OI?%L`7~4P*4vJhL3qi@Z z1d-r@Oo)zHp{e6j+Yb(X9|i+eBks=WHy~dOSD#CpiBnE#)duHsa(SuLFLb0gE=5e| zC{WW2(8LljzLme50>Ttv4rw6ifsuc1jy(jGy*O9&(9+Bt%ZCW|0dJZU^SviWUNE0F zNY2>>jR@D@6wLK(j6e1M^~{5vd&w4g|CTEmz=Z+d)^w8+l1v@ z?`wb2Y_5h?KDy;}#So<;p(kWWsTZ=AM!qX0qITkIe}->c#dZsd3ZH7m^F@Y0>H@m* zu;^3$xg0!8xl%>gLBX*l!~?vC<0DmP1;YuNpEVokYSJvv221Q|sn~L(@GndTSvF1^ zm}ozl5@QOWETNEmOxVTBl@Xq^Ak5c1ZevGIm&w%JW?VVv^_u0j%bHy86M2uRLy%E} zoNo8vHb3QwP=JSzm@b;J~_boB3F;mKIGd+&RSM_e;`YtgK+8!WPd=P6*Tf|s3Yh56IX8r24 zk3~|im$j9qmFMv@lU^xCRm7`IpB9NVTgi6>5m_b2+0%%PZ}Aq|`abN^GZ|kgN!RzS zNsM-sA!N33BFNp&aL z^8DD|nW#nR#Z`uq`SmnNQj9uxbS^USd`>VHbGWnGT~(vK#BTGqp7589n4f!NVnr1_ ziwNNSK-}vT`Yf6};mwSJ>g_$r8ucp<9{RoX)gx zmBIn(9b;oAV^)j8_%j6&>K>}RQjJHIe!4XWf`wQZ-n1;^B1fOCF|5AkPUio>8IV1KDOd2js?VG0K-?C=cZ^zC9jLGd0#!*AM1N)l3 z$^6Wu$$SfoX$qK!-bz=|J)5<8x-A|o4Yf5TbZvBLrOiz> zA&FV(A>i~682x7-5^$$~0i^@bCN0>PnvnrOKsf-s_FqEj*8ucyP&(r^K>s@^9muEx zTrK@ygVMo3>K~x=e+-cNYf$>X($GK0)S0hCe*UO`NFI6cR|8+l4TS!$Fm)iT5Q1?7 zQOwt9HIPCb5^@LxXhBMvUVml+@Ncjjoa&eb==)cG!TrJKy!l}TV(h@BGuQyvZZ-hP zW(C~kS%6}mY{35k%WnQ3_}uKkAP4COqyPpV2mA$&1aEaVMu{*IXeK`!v-LHjwr--IRn+WQ=0y*Fua1VjbFmH~c7 z8U6^^i-#3THoin{o$*pe&&9n*CVYop7(*N;&==+fu0P{*enJa2s{Je!F=9hR(G#3z zA0MA#A2%S4t?)u)YxnoX_DIl}EvnzyrsYYk*rs1N2}#iF#aIJzt^PNb0{CQ7S}Z~$ zio9@|<(AHITTjJa6A3&GIWcn=2s20Mt&~Y{>3$ZPfcK+hBPI>(}{ za%@CO-n?Bb#hUdT%L{#PCfpj|89Okz4K~HS?a@lp>*ZUmjqe9h>cqdoq1bb>M;B3= z2c~`bOzVq7_y`AnSE`g%xhAPPQD)=K;ApR%{^jt!;3x`eXWY4_6~zehf$#L3nr{2Q z8d1Ub4tzs_yTru8_S=XGe&+t+M&HDm{Q5@!VImI`H)>`;@;T!6c|X`P8!-CdWqKUV zslXsnec{p&LwN8!jpf@8M{QYHwU!p|t~K zroSG#EG$fPO~Fhzg!cxl94!8a`3-!Zuje-f5)}q8Ck)InV7~O#@8fqMAy@zEq9LQ> z|Lkgin^SKtfc6>W4A-v~I+_684vf1HuKGH``}M2I?|50@mF15w4W$3%0Wum$l{;+-FQ=wdi2CbpgN$17#z}vIyw|$Yo zr6E_h#A#T{WUT9)8QxRSv4V@jR+wW zhT_XAAb-c&C1)|mOqSm70mZF7ivey#f+ux4auFwOTW*iY7nsIIIge^*0|hx5BMc%o zgRNtcUTQMRddsQcr>eanVO4R<5XF3W){@Dl0%E!tGgs~!j-&m4&)CfD$wquMD!uR5 zrectlfn@AE!{Se>{LWg^ik>WppXA@w6zKIJ>Sim~tsD;oMY`45eyXUFap8(O-0=zQ zS*CwAiycC#MKM;sZfxt^-Cjxw(<$S-i-cYKP+}ltf1CW-CS20|VOFQ{Q(B5Odv*JF z${PW8;mu+8qCx2?W})BB4R_Rs$%8CYbkskwF|Q67DpJIv_9@v^Hmp7!+g#aubX@@_!074=1#Pgb1!$Ypz9z;cPMgU&u3zdmf@ zsnaiCb*@UJOE;d%l_Z=jT$m-k+CEhqdibafZZ6USA>~6coAk>p(L4;pI}RN*L~<1` z18`v&o3%=^m#f)Ms@ZhEeM=?HPvssah+!3v)XZ$h#mB+c7cXelZPT^u?U;}3l_21c zD%L&7iAn!_>T8hix>#uV?vj~Zg`?!s#`I#gwl=7l4?S}}*n5V+ggdHZImc429MMWB z;5FIf>G?NS<%5_uM6gH(&ud;^3RfL1Fh>XvRxm$X81!al6n`E$h-COYmN98@(3y^S z_vHU!?Jc0<+O}=cBoH9DyK4yU?(V@|gS)%CySux)ySqc-?(WVfd*A)`zUQ6u?)$&} zMyoYP^)Z;VnzdMrV)fpqE1u?P!qu)TUwgC#rl9|n_6oILq7`kDIEhV6+)%%nF2-uV znUC2EqjpN8#1gRuovCa++I=L4EzHM1DlS}nIkvEkB3cJ3g#f=y3BzimOne2~r411= z@&ucvCJX7&pI@V?yRx)sxs(&hCF6-lVxX2fJ7%R@f^0whxb^)500OlGKk0$ykf|qf zGoy?R4p8{4o1t;ym+gK6maeYqj)zAU++2?58`jrahgJ`0T^$q3`9N({0Re`&B!B?= zw7p46`Zj+G-4VdGDW1AOM$X7Vap%)EtK$O^p?9tmfy6GJkem#*6=Ca_S#UleIU)Zg zasCsOqBYZD$mHT-^R=HAtHSq*M!e+T67%^Q0GUqqn;bwMbl#5ufupP!0#$!x^TdY$ zp8$I)zzP`?k)M5@{Yta_!GmN)Ylo}jo@hgQGG@vYG{Piy_7K6EF8nDRe-|3uxA5-~ z-@(5Y-^Rgav;~uJh8KbhAtexK_}SAGcMPpt?*z`}C+Ue1KTRFp@DPL$%0KiU4bDM_ zk5*k`(@&gWPUn$~&0}c}&%1^QVTtLB?%Py6@8e{TpKQ5fhz@jc-B;aXw+V;+3Ta_n zn4iZkNOPvVgHmlS&%8ej9W}9#V!5)d=rDR~hrFGaYFM|=O=04cBW%A|n2ofaVVy&v zdde=@D&fe&|LM@$r6(FXx$!I-I9(VFe_dPzTa{QhV#>@mSQ@o_sY{$^d5takj7a_a5$5rT6rfst* z$~aN>xB?#QR7h#_MTDTO4Z9%dA(}sfY|enMLd=v9z9fo4#bIopHw>PMz$`UPwc41&) zkM-o}jw@`&T{B~9jIok5WZqYu6!t~{FCT(RmHm0wOX$WzKO}2-_e%Pr%Z_WYINaWT zyEqUr=IC%V?)J=R0g!38dxiLgp-<`Da`6R8;bRB+HVKa>)~eN@lW}>IjEc3UM%}gO zyHl9{ehpWfq3}-;6g-b+fgQ%41Hd{FrPRx0JH|FZZXbJ7!!^Arq*!_O|8m!@4saSx z){_{V9}^e|vV8I^*H&|LD>&McT`12;ZTC}Fh>MF$NQf)*u2DPps4K-{@wd;>o)v8g z)$Wg=Qe$0rz4XqXSUw1N_0+ z1++pDJjx^#ihO(hxpS`dHlms0nlOc$U67Y#E-y(p9n)5?ex7&+h)0zitTS4%{ES|8 zkMlN!GBQ8Z_k{~DE)&pY(GZMfTQy%)6o1yUV+q1d?kUmv;7vQZQn0LZemP%8U%7!# zC}rr~0y3y(vOZ7dyt+eBjVJPBJ98;arcJCu17E8sOQF6_SrK6Y6SWV%3v3??2#M-r zVN9G=L(t!~M0gbLFI4r~p zO{*)>O1CmLpC3zu^)4xY*9S9!iNm_NkyFv?bPy+0ztOxF+D`}*Q3BV?6_k@fMMsNgq+!4K#p&G%4$k2(d?)k!XWmV zL)hhiuw&!vF0NC2k zs&2s_;!yR*1zq}wK=qaBl5SB;xVL!p&XJT&Nk~-fN>z7#C<_|Tn|HS+4HiAS5I9Vl zt&1<0eq|>FcZ&9YX*or+Vd?84*Ivk}$DADX>}O*!SRiOa!q&JjXqcTt&>|p`mVsYD zG0#73fa{iaOJ7Cf4}XEl_6pX)nO^Yi-h5&36**qBo{L)U7mxnoL9m(do?phm=$=6? z%{s-#yQ9mJY6C9Gl5$MGGx*www&H5;<+)i#E`*EC><308V?BI|Ct^rt=VKn|-Xw$K zgo`NptFLN$n>r+eXgnIZi&s0UQ8+kVnAl%m*(m-q0sm0){(Rxxr(XBQ>}kwkWG}8VDUMH%=8}V)&0(grQDYAHx%a1s!87pyr${EB_^U z5+xvd|F}}>v4`%*LZF%q6%7r|j4G2glL~9QGN2~b_2vc*6ZIh}0E6BV5>$r~O&cW9 z3b-zb30Bdjqp0JpYfSprToY{~iap3OE=w}|OpX&iz|%%EDl8wX6TuFvj`?PZcQnCMSVU3U(%DTv;ZHB!mVfQ|GCIoxMKgYv22g~(nuV*GV3a4_Itr{ugcaQ9 zkTysPZuxMg_SapKyHc0x?@SXRtf4nLn~ew&9P4x0JI-#Qm=C!%ygqdgS+PB?yr!{o z&{|J+0^97&=dr;M5z^}#NMWcZcO|W2#J}20rIx<~3TKd*70J;2v5C>FusRLQsWIaa zr3tH{P;vwaun?bLj7t37G$KUhidBAzkcZXf$Ji$4<*T;!in)|%99z<+LMsNSnjsiz z!E*t8d^D%btTxY@fk0Uq$`5LAL6Pl_E)EapZC+wSCdfl9gw6(Xq+fC~0Gf5Y5y|w+ z7=eO?%Nbm_^7@l+yiwnP$~`jR5hCWeIPV`BK%sS8pJvb0Z4>l8lOL@@&dk?u4KL$9 zQ5iW2dxz5u?TA=_3gAao5f=#H+esF6BP(JrqsmT6_N2ld?GTIx8y+EyglKcHWkO1z z;~mpTtIW)$yrp!Z4keq+pv+^$oJmGVM2JOH;4#$tmq;6jF87#VGK?n&CJSHpg5vL; zP@3^>Puu4JKI0ET7mf)u`D1syu5OVqc1Xft9^45YniQPBU4uS#`-=$mPcX~Lxwi`G zkSE;Et{mD-V2NX|G`kvH?l{!ru%cggXQz(eiii*h>Y9Tc*n^DQG53qo<@Wqo|D@bbWY8k{1A8-VfH znf+oP#~@7=mQ?HVKu{MGfn(v?aDTHiaS%`BobnXTfGptLgumc;3BN9OHx(XA-et$}lIKvft%;i%b zfH$S+!Nro3?A|~dxnH5S?940oLnvJPy!tqCJ_D7{;;XEiHJ4EMw9QTc&1IfPL=eS0 zGD6uqhB)GB8Jq3TT+|c-{!X{^zxK3V1>5(64=Pu-vv@b zd~(Q5zF{#11fiIB0E({i7JFw>V32cQ5jPKZJP+Y>SoKgLsxBNLF-I^cHx0Uy zx}SI+7Y5WwiON|WhMed{2kCLqX!5}^8e^qZb&B>GQNX2WQXXv}3?UTy7yiO$c304> zwp5)9R0Iit8n*7W6E73X#3Uf`7rKDpl$9D>=%x_FcHiYRm{VxhAoJ8sBKu4&81h93 zBt+=9!Lj+$@5OF-UBU?Aiu38q>P|1#+eI;9yw|Iou;(4UOe-Q@1}`PjR5{XAA+~L? zPHe-d?!u^UnNTu715;lFwmb(tYfvCjvwnX5oGK;DAB~;eWG$vj811A9y5xHs*i2Ep zW+44N>A;L+Fu02+Z6h+xpFbHg$hsOYV2?L^WlpPJxRI1PN)j@xhZ>UtmH@(}+c5Nv zWmt9u&%PyjmGwJ)!|+OkgN!fXI}@z)J{<+L0g$6AtO=-N48C}IAtBJ>FkcT8Quzfq z1nzV*`M?s+X(S>KzpTfUeh9`S9(Sh7o{#$);wR-g<(}-7jE)hAIvXx&J(x4E-odD} zuiFZgnoZ@_bJcOTOzr5cHaoM)YbgqLD{9lWug)_F@4`v?^l1~ac^xpMbb;ZxJF8w&;Y=Jc=XO2I8h9Vl2>5F1TL6+#qmoymhMd6Q zV-sbI6=ydHL9H42fcX?!hk~gh>r$3=n1!%vIjkF`PVYS0%^Y&5Yu@3#1gJ4~xgXnh z?$qxn($(Q_I9qKI5O@4y{%qj>DCyqN+G@@b0jf(nb;Y1o;&{bo5j~?%a{(U|1fNGO zD?m=qj}`WlNT+U)uQzKRFFtE(952cZVK&9*E?E$2$pnj`{oqqjt3&Rwl83|U&CNaC zDvio)467QWgssK9EvLFL%1oXu%W7nKF2;4wHP++!OW@1kOX17GOQNeHY3x-VZ;{fE zxZym1nY>vgG>yYTTLnQmK?Om1LB)Q#X7~gCS0ZyqV7E_}9@t^lY+D9UYAgnd_8pt6 z_PfyJqi(x#jYf|?1wCP(-6pC>$|fvFI+7Z8M&|WauFm(2h1`c@&mLdtC3)j6uC3H{ zbv+R)VxHv00~G;s0{y*0gOG>DM3j8-SP8^6V`De7s595x^SePa8mJef2gJ2k&V3g3 z<$6AcZ)~x@?$0#1NOSAb0ZIz>+WROdT<<2w<(_Y#+lhKFh_zLUZ9vq^k^G|!jv{Pe z?5ya_llx)Nt+H0Ah{af;;N96>UYUVPow6FlLSHGBw!!tJM}#9MeV8p7t_{$J+`hXu zh85x-7H)L63MTUyh(H|Ri^P5(&h{mBay8Jy#ZudzG*<&O zR+~P?A`xQ*&y{z3UUqwf6+Z#Bk$Pg)OiI0wH264TRn920eTuO~9e`U)Dmbn+T}@Wf zBWPOOlMR2WCC@jCha3RFl*#n>hpoxtWz}cEfvPKxhYejNOfe;+zlWOhuIX&ST9vZ4 zG3#JfeC5bW_qMAuio_Wzfsm7|AFczLi1@~!Cw!`__ML{+#+~4q#^PX-A}0AE>n-epU#onu!WC{Q+N-w5 zQPrixd-g?0ITH<@*403ODVvzXZT>2r@t~4e&4;B7q4BVcDs8&@=5t+{`i-Lzr%u0b z{r$mUHz&kHcQN^#WVF#R9Gw|p{5cSAFlsqk2Qrcur?BTJPPJIEymYPlY6YgOtij{r z*R)+2^0e?B(;YJ9_PQZ3g>Hy4satq?HklDA+1!4P4MTZakV>0d*ittdVpv=#IMoFR z&xSyN;C%QeWwtN6r;eVb5pVFy>o0oM(3Q3rM(g`!;5lAQ%|R*smQk={LSR$=--)IV z7>VF@X(*+Ikz?|Jn{r4KM&PXb)JVn7%#X-W(4WvilLbcv{Av2D^3hhv6T2qh^)d1> zP%K0I{H|*JHPK`#M1c#w0>OE!T9J{e1y9BtliDhReE$^(SRvQWul7|133nb-RjgE_fWzO<9d@$HF^+MrL#l zg#f1;IDroz!s9J2>%Sv2WA^z6%uaN2SgwnXO{uYtnm2=7#86C8+!@KeWO}1eKH|(& zEezYJF#wR}aQKP!;B3{vm%ctKu6iFpj0v_-fq80xyCenwXkh`vv2feyJybprHdLN| zI9Hwi(A9I9iP%arZ2S zWo(_kA`i7$7<2CB*r4dV=UjWHF#frI#(F&k0b0CxMY-DOPDp4m;!SxUC*!_r^l0hv zIOE}h8mfuCnP>5hr{PRbN+Km`WAx!*Y_B6X-(6_*lu&+c1*Y3KxMwHtd&cleYmI-UD-q*q-|1QP=mm2(|68%vVHRFevNe5z}H zK!V#KXD9y&pGAbHR1NAIIawEG=M`~L0sH2(BEG58B zb|vVucUZ8+abliT=M#@z26wjtXNfy*x8T}Gb5@n#)?#$_i1{7JI(4#E`p zk`yGv4C$8C!&Ws6?(An0LLdN%QdiIbHE<*z8wJ<&RngN^ty$8>W6R9Zv(w{AnILJp zpnX;K_Nv^X#2n`$qQU*Qc*bamZrzP%ZV3aHZ?^HWfqrsZ{Xh)X?1_#(gu_&m zbE&0Hc)dpc;8u~HW2X6aClL(?K{ZnKYtCDxk(0wc#||=vXsYm)pC*+%`5n!_W2+}N z0nxQMr$`ji?7pgi1t=g{)$sc$}x-y?>J76PhG-bThhe{;o06=JA@q zg*ed2-!NHrqqk!0z1-5+Cbj+^A?3dnQ|P`U3U@l^D`UMFPcz~E5FG0a|Att;ph!(uD9j`FR5niCSgGDI_V`0sIDX3S0`5WIW zn=nbV_uz86?u$^<`}@l*LA_yKeEGmOq=%6ZQTyU|Q8^Umn{xyYndT@HJ zW7M+*ZXiTyCJH>Z!aEXwBIZ5J>d+nnrY|mUo?IaYT)1Rb%iQ*nEJ_Q6s$N$fl6NuI z)-k4g>sBXb9||tTNPXG}61gt63a~LX@VjOl z1MWe&YI#FsMw6$`UvyXgcQ!hqN>odEz^Q)u4QV&jW84|+0TWbsIa*)XzoHnSWpr`@ zEeI2J4vA#i zqW*yFW0~l*QN4B3)1oTg0c!Md)|{YW^*jfCbkzICm1s)5d^too3yEigiy@T37Y}9v zgi+K-A+H1>zt~X@mE3oWtJ;KCi<#FJwv-CwCX9kfAlS$=eBgc>!89$C-L}h%;vxpl zADR2Bv^n7#5&8Uks&ctq_Gx1%Nb<7%drATx%-fi(0jm}mOqt*5WGT2J7bC}TP!=2hFJkJ-9ZAkcg*CyZbq?;Zk)i6 zJzT99k4(;_ggi7$K^OY%lcH$PomuMlo8Wxy+~7}VVz=)jG^GJYE~CL#7IVkN?G3nw zpBRpBBi%IbQJkF&!IXn35Q^cPu#KQ#A#2|tpVVo;!2T4e2zlc0*4V$j&dk`np_^rk z|NLvR8Sw@3jJ7f6+dC^T7o{JLxgr=B^}{BZ$Md|>rv29y%3X_9aYXYlKUIx4ef*c} zXZpm$FAP93=o)Ql#2b4zbWqg_y(c)K5IBEb z9IE787@@jWBXW-W=$q2-cR7LVbISPIKyu1#ko&-(r7HhI8t3oH=-vbZDJa>HYZ7Aa z+aUBo5ZiPEIj3<<=(?o9<3;fK1sP837|;cGavq3L+@t|1#cm#zZq3Y zcRiS+vfujm%D65u=0P#YdSC9_JxN{$pRu&gfbHkvOye26tl%!<+A@g%Em_izOM!?= zD}2+ND-6_^tC*qNiQ`vG8nsNgdUt26ZdyL`Zh>GY|uuXtaGUgz|+Z%sMuNHMVERIAh9QW0g(E7 z-J@(5i+G7$TC6@gAT#;RzDAJw@bZaA-a=^N+SEy1xmJSO(P+fTJ-+wa?2P@(+Np4p z*&!#?{#}M3??^~^FN(yWI@Hl!U?36Xew&c~0PXKSc=Yn9-C7rTsI%B0$gF-|>Y0@d z65nmRJ=-O7j(H9m|7J1205_oz7>FbY^hwtg zOm~lr-^CZOni5{6AB*x}eb2n7T0Q$_kfqEvCZ7wLy^X&zWU_?-2$jgSz8#EXW`pS? zBmy-<@T~fMhxKk=o=Abznl>$gu+Yui5Jv>@w~UmJL=9Z58|1D8+Su8E27xL1k^qYM zHM59YF7vjw(Ud~s(PN+Q%>v@W;~@y|9Y~+UW$@qdhW?;a{N`AE5GR=FKgg4RnP)Qp z#dZCse+ctmuE75n46K+j^Biti-*fgp%$fi&$mv$x^9at&=|?J1R`p3|e%ZFX9xuYMV`}JR!Glb4uPH zCLTs=b5T4Q0eV`sz|LpG;Hrm$H%*~MFtgknh7EZ5wXiMxH{JZnz z_ZjeC=Lil2u%w#3S#H8iP`1Opn73^fS&21zs%>STC{WtdWpK09R zdEDOx|Kvaamz&0KTG3x#A`Bn?+!S;lR4=BF%^zu~KQ?>&p9s(&+JWDUp}z^xbbs#m z@;3qc_cVXh{Lc*N5B}^Ql%;>t%>Hn@{@>T-&l&$>naNq(>HS`_KhVD!X8(sZ`p^95 z|KKU|$NTgDivRqd*}IG%jv&7uAI#(bivHdBclN)}^slx5tow7;e?|Tk{qy->=-;#d zjsK4RPmjNU!oODi=gdDV|97tPAD7F2zVWmlr0l<$m;Z~s_9w~h4+h`=2Uig@S@l2+ zdBpTGm)qlzr6tdwWZ;|+TB_1;a2bdY-txhSwMYQ7hGlaHCXWG|8?=LxZk7PFUkah=Ar}TlVY4>!|v? zY+$X@z4)L)jnfQ-JxjTsX1!W0Zrpsohg#;6NDsKrzt^x4pEx%kyAaVKxtpNAG+s&p z$Hfx&_e1qHq=ys1Yuy@?Kv>I%XE;`=SrsT)R$^+%nyagy=W8k`GjWR?(YaV&2O6Ps-OOOOfrfh? zeGC@qrNv_~2CoEW0|@8fG18W?CqL?U5wGMe_uoRB+tx2E*jLrhyv;U$z1DvuUj1^a z+aQCXbO^!G?$akZcqhMEGG?6cZHAs;oP?T+{2?bM^7`a@JqZB~gneh?X@)b`ZKTT) zObm|`9Ud0>CCRB9=?ZNM`a#k-&7OzDu5CJCt>X5?q|iaN%p9vkLFydAT*f00jptX@ zR?gvjE>v_3_I_R)I|irV$<_sQOpwv48l5&z<`;`!&()Onm}r@1UnhZ(vRCK6jZBy% zk*?JfxGkzG`~2kLtElauI##|5uR&%3&zW_rOXjWLdod&blNv+VCF+U-R4}5l^IH3J zmgCPGILhdSz&bdS0>*=x=joG{aVhKp`MkSYe+8ZvURH9zTsg-IiEiLTLhdQBPA0usgc5(s;*rAZ09$j0{dZ4yVuTGBfkFt;AR zUUbbuN_g+hWy1Nx(fq3a#5Sd(JeC=Ay4T`caUkf_)15zegw8eyFZQq-h~tWTl>tDmjNUwsdR?#uNcC02lY-CU&hg=mLj2(a*;JhPQzGw&V%0YL7@}BR9Pw=a z3NA)%(ji4dlpz%$ME;^KvON>O5Cn;?@w=1q3oI8Tm18i} z+$`B-m@z<4W&zz;l}FWR1PcwTsmxZc_QT-Eocl-BfsQo|h9G0~9)dJ*0r7*ww-7{G zKXBh*B@8Po3M+Tpr88nPwgJEeSQTK?>JGljZ zipZqZg2pI-_2Cjj)PkjOIq}j9?pHI4fJfX9+-1R6=Cfe{6<=!lZ#gm2^y=zAih(P#caymxny zV#%e?Ydv>0PJ0QPPL_`FO2>wm0j>?+hihQ>Iq#QR=v zgc^L`H#oTIP*X%w%xTxt-Ezzw&d1Zr zHUTHm+PaZr{(M<~#ker*sJJEXGQ1?D%*>PSbevwW&#-D%#2{!bXRlnUi!i_Gw%Qd? z`ePrZvjt3WSf9re*kBH1{E!`g@`OZ#qUXL4JODGCpl1Ym47a9|ax7pGI*1 z$yx405k*16^0DFXhm9E1$HpxGLofJI^51*GkMI2h_`4VUtK@%f1wSm({`mX<&yIlU zpJ&$JFZf?t!QamJ|Jn!s$5;NJ+d!H>9q|5DCh*6i|Nqnm{@r-}YxJ-3wtvn4r{}+A zZT~*^Ta@-Y^Ou0_-&Ot2{fYmUr~R82?N9m8$1m$&pK)1!m;cqA|J9;>7~=h33k+!J z=@|c;z~EHH#Zp&3iEH1sz@ph=`dqSOI%0VuwNxM5c$YW`-Fp#g zE)t2%m&6oEu3{c1vw9@c^H>pEj-M8A8c&9gBizo?FUT72lwa~~Ukn&0BW4&i?NLoRa3i1V>f$8 zXiti_H+@e(+`BYmwO&r#PQJYiQ@PiPKeXB%67iOa`F7f(SUagGpB{`uG!sz+aIKx?7f+;8>UGyO?Or9~(DeUIOJV80DDh*Ttm z>z41tVm;@tAVL9EUbbv)l&ZZeJ%N<6q^49J1@fCJ>sj%fDEoQoU^2I69lSy48P!DX zOWT2N;U(onY~iqbJ@J{lDRWKADSnp{DGZ;aHAi}s$anQ{7OB*sv34_h+G-*|>{{|T zl3AANWE<>>p_Pj&+s1wGQpm~j$uptAnL56aV{e4l)#k%y7(IFT<$x774bRJ`AStaN z>Quc8SxmE%BQi2qJ->?5i#VkA>TX4ahhcC{<;{PB^MB@%TnS^4t!&WTzabw--f z%A9Aj#GDeQ|8g>Xkk&AQKkcTgo5nx<^(~BO+Is@|43I5q3HPX zHLNwOYdUTjC5y4-AQ-7dZ$}kzjWdRk7{7eHx==S8HI$C^#yaPK7}p!cM?1sVI!pBx zsi<$~sc(ZF$VxF7zoht3be9LTq1dCGa4z~(4rpV}%m#04(OP|?S*zoFP#7!Zaisrz zU0V29i#mJBp6wiZT?>7Nl)jTSV|y|lG9n&akF@He7)t1tSH)}O;0-7mQ$(k_v$#hY zu<1!;j4qi$v75WcbTqNB&n8183+0SY#~BO1uN{v-5$tQuEp6ik1*{6YI%VrShs2*U zZ6%QKbDBeBd4t+9BXkRTg@(?pCb^yLs37tJ` z95x3iL0NfK-62dK$Jlast&(rL>YH0ypHVHkk-2zj0=vH*&&HGpXC-97*WRD-KhQsC z!WCx0d3peG6MUlo^6wA0lVDola6g%&<+0Z5vd7lIWvQQA{l&3S!l>83)}^&yJRwcs z8U-|u1uz^e6)Ay?gplMrAEmk9|D;D}5*4#Uc$SQ#DtzV}&akyYnV1uTr ztgRQCo4^uVvjcKHv5&r0A&RDT5LKgb2BO3H&rlbViq;|Ci$jT=zTP z_?&6Q{F$-Ple|ZYXNu8$t8y#wDEqWIjG?MVEq3dNllqUiL#7FdIAyoovJGhw_H-1& z^7adKcrNKzqVJ|BNQjgH*~f_HfD##0wMQ)LtLVX@dn%tnZJJbA|M=4c<&a z#>>&WFz55RVbcsKA|J^P4!TR$_7@x^t;5d(=K?Hv-Wm8*;UW7ppweZmvI@{^tb4Eg>KOdg%fw= zkRB8=HN}kiol-EW>WHx}=0E7hm((>G~&XOj7MY;=P z5REZQ-9N|95;R8!pbGtsImp&zuir_*g--6N>clUQ=y=IaEm0-)cK6`Bd*w#(ajErM z3ujv!yE#E6$ePrp_LIKr0Q24MG{f$;{O39Qw0Py<-9llaGujC(CHb6byMTNc z4P#DxG_0t|Dbf@(8kZ_IQ@SygpXQJ=yEIZRD`mgfj%}yTrgl&@CnC9qI`CmGSo*4U>(m)oAR9*j!&8-sTjQu(l5ILf@Tgb-!yIsB@c57k}b#p31@z0fWz( zm${8=DeQ5M3{8KZtGWh7UVH5s;bgZ;Tq>F1dZmx^c;BU}SfFC`JqUX@xE;Znr+k;_ zgQvjhxQb99SBQ#xSL&nv?9mt*q5*Hi4vO~DOiMM2f)F|xc#WLi%)fR~ShdY_;t0!z z-5U=2pTeTP-#O{JMn0QjzJv45{-?I==7Ary;lpI|b{4TejNKo5YtO0yS!9A+ifZlm zAosOy*_b1s7;b%4u2lh)CuwJiY^x5B4A1&D9O?1nT1U~F;sKLV75JJDea$iW7O(4* zQfPJPtEEYdCZusb6*CedT&txi-Y0i#1DN7Ch9$lASXkjs5ZiexXP?O42V*eI&oeF% zNm{&HI#sCmoqI(h)y5XQ zh|3`14X^mna$>ylA?fupNr5EL42QX8L6T`FV}C=t=)WTY;#$p(**Rv@p3!55f_c?B zr1%6`9b-LrZU*iU_}9Up!{FSV`d)aV{DqnY_{JxyO$va1*BWt9y<*1Z$?1e=8@q#* z%9@BI{;*y(`S`)~V7yFK>dnU&yA!+tao5557ZZrXNx=aJo={~w`9N`e?JNM>m%Uk(*YrR{iJ&sBH&?hAf?gzx>7H6sy)l=O8MXuaE7>a_S zCAT1zWfo4$f!Q=n2DRP?6`sL$poI6X2iv7(FV~Yys-I5l3rY8rv=9>(Ngk1p8+|!9 z1S^ry<`o)wXP3FPt)!m|!k(ig?nib*jMu|GGPB&c^phT?ZR-NwPLIfR#!mH|s`lz5 z5mp}6l)f>-RR(!V0Gr}#A$(2&TjcK~{=#TA`d>j5`fo^XwZA4)Q5C99hauFw)ITLp znJotz>{%s#awp|1v4T4K6vuvFC}fIvkymVA-*l8=fy2_4`K)Vb#WvE8W0jU}rM+#s z*&}<$h*Z%+Tk7P{@HCZ8edx64JH_SEh+59oYsh)kIf3)`jw)=JrHstXrljTCP+I-f z-Y5nK1V>j~@E||2F1{=ULed5-!hsGiF)bcKQe=?$A20%K)VHKTUvb?(VL1uyDO=yZ zW@Sy!pb9v+NHca^6Tsl8`Q|g4UsW^}r}Zv$dxzD6y+ zUp+q7I~L|3##aBGuC&_0VhA20FfMPdD8pE?{7TvhO8byZr)nrA%@Vy7MgX>k3wQ;jXeQ;l|<-f#1lOJBOm z&Y+2M*aIAN?7}<3W7n6sjP(3}stRSkPiHkUF-4C^G0?@dBFuKqrA_ygDvWI#3c(xKkNd?^J7TN zv^)3`W>AFmRqJTd`%%MwViwO6G7r3p^Ur0?6hqsYiY9e%IS+L4uo{=R(}-2n1aT~4 z#c(C`Em(bMta%1EDLUCazh|i^1FL_lpSIHc$xGdYFd7X9p zzSNANHa`w@Qy68Cu&X1R)`_nVhMt$xJv_5&o%Fg%@^1b)sEKkXGgUHtb*4Fr9oHqh zU(X-1WKV9wtM27+-e1Zm)?A=jHjp-tg`yNI_I9X^cVHnIytDez`I__@y|VP60mZzF2c>tR4A96C%9%6QZTc#N5X)x2~MwG1ATj{tzW8i(9>i+W>`CgIMk;@e_L3>{o_Y?mXsDU+OONU8RlX> zV(__{zN!gBsS4U`^iZQYTn{xl6%Vysg#g!2M3;qy3OMNVOxH|id=SG28Z}4~9V`>j zW0Y&L)J)39ZF#G^Yp=`MUg1;X%e4tZT_-=YT4EgtU80vkQzeuHs>h%*R%$BduWDck32xm`hMR?}+g{GDPb( zC)0LZZ1rrZV_3k(5!vkYmh5-s`XlZFNyuiH5$9M(F-(5Ke>;aSs7q%f-*3B1X{-9I zUVSyVX9#<*3Bo<9^A&kopk0pa=>c4E+SoB&aMqF^f5>`DEJztsPYx$;BS&UTi0GjZ z_;(2JD(4*`dLjLd^GDY|L3qG0WW~MZJaH{~9PF)|yBk-I{PKih-Mqc@BlnkF`8hFZ zpSu&gZJrsESiS7lapkiSpzB#p%pqIxJH50qJk9;|^71xSo|P!^<f@fQ@3 zdX}x-hsjJjfDI0C-iYQRfYWlpa=_Fh*KWUS{KhdMyI0v--=O~G_L5?=3~RXDY|2aR z`iTy*KQaV8a#K?iX1?~ogM*V-2HHcD70#^eX`@JdiB&tAhZn(}{=BU64LYA~qWsPn_nI2t8hJWXZFjRa zK_$x~{)zLVi?&18nGXk;3nuXqX@Y+##CMW9X5nJ_BJ5%zgHKw{8Xbj?!WCzLqjeqQ zVBKf0oiO|9ynLk?MuY)OV$#nFy=SN>O;=Cji6SGh#98Hh$LO>2wTT(_Y;Y%S# zG$~RMsCOdp5Kdvli$twc59F8eOW=})4GDhA+b7?A;~h*X@0Cg8K}aiDpfG2f#W5z$ zDl}(x%5*6v(MeJi#Y)#aCn&uv4`2H+HGT#i6ZGfPoIucB$Z;hawgEI5g*}vUqZM?lpp*zTuas}b7 z6kb_%`~5xG)%z?f!17h_v>9ljWufBz5~Ytr;UM5p=y281gV)6a=zJg(=Bv;}u<^RN z@;jCe5FD>CTWf0PQVfEhHl_h>MGGH1ub7*k$f`*>aF!gRt02EQvC6pHYY11|rj*~! z1yFUyqJtS92-D{W!BTKe*pknP*516>4<$+GlyC3Hc2p!*-Y-csv-vSK_p;8*EAZ+q zdO?sNj(E9jj+szs#0bzZ6wv7f0hXP#%uzCv(|X-K`*xR`95qu-7k~>ul-PuSz{k!J zlpGZiAyR70&i0fToKlqO>b>hl%DXR}sUB@kw&vxauLn+C&QlWrmK)2a`JUZuP}|C2 zsyV&>?tQzUA;4c5d0~y{%}W52n@xPmxz@SZt=roP$9fL zb$AocjoE0ZIy;+h)OT0He6CX&ry4N~YIfzu+Di%RqQ?oVqTLDWqT4WaL6!y_3F?p9gzKI*mS~-nu#?^_3Ln?DF!ot@ad1Pru#RVT1$S zjF?Dm#drt>a6Y)T9$CyQBqdv=T%Hk#*W-uL(WeSXj9 zkI#Lc+d0V(Ubb3h*5 ztgPnOt^&mjgV?5)hHTG=KyvSaC;bIql&JWtT*6!GhtOVQzfzZdq)XB+(!`9n$#Pb@ zT)W!#b6CyYrTeqC;Elian{;u_Hb*|uTpPl_Kn<~v_l zt%%yI_{9W3OJZ`DlsT6wf8W#Eb*mCe&)@f<^~f*ZS6Dmr~qPCyXA?ft}G+k z@~;A^^|v+Kcv3QL4h_Z@%xRVK7=58ao#NBArbzph^o@brM7*BD#mv>z)od~TRQ0`g zwRu%;(gC9GMnFo&ds^T4rxQk1d3h_w9?jO=6o=6tpK27oUjC}sB$U;wf%vifGyjfBxdxf> ztI_L?ZAxFSd=0TGb?Qf3lkp@05%4G1_;1ct{gUCRulQU7UL{^U6O@c1wF)R=aMf_< zyKiOk6GqI@HK?jTW-VAe$MZ$$WBN5t#SVS*33yE#zgE}@l^^r_#H4!1_u`gap`YB_ zr>Hw$d*43S#>G_b`F5P7u%e}N!_*rgod1|4XIc|Y` zw>YeUHrGpU=D5ZEzLnz^_Z^pq7x%gTKk(WdVQ|5^#N0Xc+&p{5f3ClUw=o5K1rp(S z??1gN=WvxoL0O!($Lavr%Tfv7)E46ECO?ToQzEHsVRTRoolKR+uHbD@ws?oYu6NQPLIDbWyMj&S7zNqpZngMN%J*zcUZ0didg%);3V|+ z{60N8bNTx0WWHn1t-4^Ny)2_haj_$JXqXNT-?OLp)$-;GD)4}hhw3m($=oWQSg@V| zwVe6##pBK@&TZ|ktaXS z@U>4x)LQ&tCCPYY(ML-i<}4Wpcl{-wsoY^+b$Br4taP!_sCDZ{$E=U^{yx)*Nqkxp z0?&CM5)#_Scn>)}xoTH4YB`d-S}TGrwl|eB?@-WiCY60edx1Gk6xQ>rzj~U5p2I5y z${9`lTp(K3=*Gn`e>YcH-?wYV{$%YYzM=X;Rd8iJSC?V0u3$k=fcRlakr@S^hqM<-H6TrD+=gYR@>(C2`Cq4_ zaY=-%_eEC31aBl4LRG9-r?lpN= z=|8O3&bc;I@YZy#(QLuC*c(*wD$M@>1N%(>9<7Kfe2<`Vk+P2enU6>=v zBXeyZiXizBzi5@szy9ny=Hp)6uzb-P%=gAf?LCQ0o*a!}dZ5}_G1`?0I43=KASw;LI6zpx#=#hQ`u^Eh}7mSeO1=qe*?i z2O!B{`Rhw&D`axf*w^6$_k9jsvrL<>>7RNru0Ozo=wNx`nUFqqOL9y_iT#^avsLo& zW9uBrxfm%|swaCHGP`3xcbL69BlP}`2m9aH&;R4tPo6FN2T*J~V?Wm)sND*@+qR4T zXfnzvO34Vx;AN$j#Ta27EY@wQy-h~oZS0LQJFg9GJaB-kuytz)3X}tLa|8K;A;1F) z|KiyM)aEM*f18a^o{f;ron|BVzcd?hkLltpg`Kto5VX4Oer=Nn&urWyQuH6`^kRrzo0Y}toF;C|cqhI`jw51S4@U=#+V z)83w#O#uM|UQ+(|0i)bd?p*<++Zm~cRUOo3HM^taOh(4-d6|qoJgH1IG(|LsJ0zJ+ zL8M0y@9Q9EioN1b3-hH$FpE|A`jdM29#v56D~n}j@h^|1j4D+$VSXm?VGvSX$Jg@n z<-K2ROUtV+-T601R2{w+m@Gw4|q-|rsDUWhu zr&KO7RZmb~p;YCFR-0|{`07LzVoSMd*7VjZon1$#XrjS+nS-e(;Nvt8=0g-p;IhQ0 zdxJzO-$^hD5b{cD>qsSy9P^eghgJrLzGb7zvfBJJGwgRZVD@ud%BXmS|eCt^5r zc9GeVOZU>7kL@C?xa7Kyw-j;n)&kuGd&aubM;Sj56|uP04K(Y z(TSH!V?rg}x)(w+6REz=vRZ|L1y`&KAIT}`M4xBuQ$hR8vc3-R6RC0$oGxE&{?R}a zxWeY6CL8Wa`flm@=tBDM#Qw96$Ij0Cu(bnEf}b3)y_iPgZ+vO8;)spqsNs{EANJpb zq!bRD*8a5h{t_PCOzb~v^W)Bg09j5S*oTW)xx9WUdnq%6wBpaOIi^MWHKL%%de|VZ zg^5k`t>xw`9UqEw3Vo_ZwN@m?>976fkV>i!F^_W|eEUV{P&sz>-PJsnK%yfY@Sw`yjqU;WZ5DKAtgVzGi(b@fEjX%DI+o z%@l7l!<=N^Ox|MNI9|o4vL;QwXZJmNpu_1~bD?^bbh?aF@~xdlU9gP)g2hA~-^y&- zf-Q?QhT*>poh8JbYznx%`Q`rZ;G2m>1?6mVe*;x9NeT+V55EEKl@lNRQr%OB+ z--5)O6+fAbT#lK=zAT6`&S4{S%Qat$j<94{TRn|=pex_=1fe(i*3Y+&2IY7r^ik3U zuQR7jzsGQC+EivkMVm}+<|JfhzIi!WJBFZ#WMlU+S<6hvGaCEYojn)-B}C>)i?IVF zqK=MPwYoJHAxTbDIB-_=VL8Y{lKUevq8iKBqt9nQ6y$9%eCvGdc&&C+n3UOwU1wGJ zi$vRsY>y)htNTk7&ew>dZjJIUeu4Q-8TJHAG&K4g@W_5;nA_U@7;=Grb^Zm*t2Ycc zU(#A6hKPKp>`HW{Nkv)MKW00n!k+R<@@UwI19Aoy&e86m+c^;gX@BO zUFT3Ul>~>eSCyDg<4;KJk*{rwS6Jt-B?pjnvVMe#bcxcu(kK?iNWJE~N(6ovL@UJ9 zAoS}py}(4HP~6u?m!7<_o}P|7#ir{Xx;lG6Gyfaw>R3BTpQbU_({pm8ofLU9-?bRO z59>JIrBw+3I0<@i>NL_U2jxC=<(ROm;-)cak++39o2Qt;>dt-G`WK+Z-P*7Tl;OtyDpUVl0wMqG9s zJLqisQOaq> zGI(i4Sd;7Z>P_Z#u0t=zQaAuw7R2` zsX+99ujw-|YI>J`t6$W#39*G7A^3mp}~mj!va-BxFx^_&S>8hFOqP*-T& z^{habQuxwH#aoNB#@*7#lftjUU{9|e5GJi615jMv(L^_S0xnTS$J3vBrPdmD<=(qb2oBzZ;?>@Deq;v> z;Fn&CU+&1*w=b=^5ZOrwZZ^mYQ7_aWx`RayKgi*EKGj&&T-RK<8aFhWGN)@lTT@E6 za#Nu+HbtM4SCCG;Hr?t)@?D3y+5-O7@HyqN;wi4$?&kO-O9hoAT=zc?Wmm)ICq^@A zq#f&@7B0wr1)u+a^WITVqTFl4nhZPn#6KS zM+5Htswjx0?KHh~RDtboH={{;xdPGO8x2HDj`wT4YN!9zCuC38y``&*vO^%(?8tjFBF9h-WNoz2#YQn-8ug z!?oY|t7m`GNByvIM!=p>S-~QF%>$(mRkNE&z2;*J=~6iB1TS)oU$KC^dpR&bYE(_3p^&Q|>_rRAk+dO}O~`9QLP7XNdb=Toi7&thGkNK@)A z8H<6a=-fBCziB=^QoWt7cilAP zJ;^`KU6<^AM)vMY#|3|<^aG?{IXZ7OpY7Mk`5pdBSvs&JL?F)XW*7K}{MW9jKz*@f z1u+kBR%6<&j%UH}7Z>am9W@{+!ZH)NO;ijAuRLW;@49oNK|D z13~v19kaM_O5kqzn)ZzZ*M;=9ulWPv?&9KPF}yC{T6ywHPz!lW9{V~!wfd0z>X-PF z)5Ml8etoImr1J8P4mmyV3qSHO8s-vD@~TVj`{+&OmR_fOc=V6<92F(*PI~V7@Do_g5`s2dM3RiAzA59$NS!QqmG~~zp=!-2ac#Ji2IXKRFe1~ zO?naJ#eDHtkdB^;^i$7~VU<8RD_*WP^15dQj-kuZcD+wZ(j%kLw+w(gSE~N0tiD(s zZb+nF6qemF=xNV)PgiSDowsdFn^*>8%f*GD$&qS7I^N)dab1%oVjzB)^MizL_1tKC z@_oUzuDcN?F+B>+j>^{kH=Ah2=y;t)%K2GKBErK$SKlX>#P#GS+QGQzyogSmkX?8) z-4@{!==<@S7sE%1BV{Cq`-wVYAC3n_zm3~h&1igxSy56*r+>VTSj}%V4C{&c{qu0u zoYRW3dUU(PJIdVg(@$axI$v zw!ISxX40h&dJLot_NzFq^huTs6s*}2%a+r_?U(Yp+MjNO)m&ScZ&Z;hpI3Q={#jvF z8bwo9hM!t~C|E6gas^#XJ``v67OHBK_LB;pkmjKur2cN2%%hq9J$=WlH+{3glhUM9 zN$I4qcOTPTd~7>Qq0W>E$v|?dO(5atol>>P0?$*X2_3Za8TU{}D@2{KbT4`mu+lE2 zR#NVTDtbEw;+u-0FKwGGsqh$t#m1+LwgnTfBoMtqJ$Oq?@l^J%XbzjpLozWT)lnTQ zB?-lcZ0k=QJUV?y1v78gfm9B{;V@KMirNW4>O!!hB)u6H`SrX=Z{+_L+vc z3x}^qnx-~ILY4$$fJMTt!3-E&r-x^y?WMS6<6UQiBg0jLMBJo97>pJd4v@668pw9`51I(h zHh!5+kGbJH@k942Bd2tXoAZ?NnUj|1t-fBVRK$FiHeVucqv%#d6};5d9B&#~D=n$} z$m>{M)jg~1*R&D`P8WO@?OufFqZ}#+(`udScYbpT$|O)<9%As6{lgDqC^S<7Q3a=l zT@-tK!4K+n=%L5H&`1Wd1w-v~icF~@TM<$WGpcu)h>zYY&=q zuEe`4-deV7$}UrrG;UzB_msKeL)=A5MAJx`a2m)laK!q(%_IIJQP`Z4aHzap%UDJW zLx)RWGNySv!=c@d$Uh=drSMn3oVc+A;8vpf%*OVzzen=SMa*=ZJQF7(}Er}MsdNOjQP{T^^R2}NJF>|$Mjp83#%D0u1IgH!X04h!YgQ)3bLlTX|dxb=f* z^-9CX#aGKq6V%`5F~)i0x&prjqF4fY;}>kY9cYUGqRjUQKX=zb6s6+; z^@Wq7BjT|#^!m7-;-|NWEFIp{hu?@vrLIRo7_f!C?p^>EfWuKVNBb6pW@tvA1pk)}*GCs_0~mCwr; zI4li)EO@S!RC4u6OtjqN34z2y`uGgn>1Mj(@dtyQ<>jt6Ll(7GNfPc|^o)sm7tD{R z?8}Puzd)f(H-Pjek;6Rs97Ot)NA~1x+Q01R9`1YbWVRyd*BS2%fx}P7YLiWvk5~0* z`IC>;j{QCaFLgwJcIBHnXz+=NzvY6m;^hHm<`<>?Qbr!%W05cKA&nn0yp|1sR-77h zeLc+w@gepPHkxHcaK(3}c-_i9^Rv6+Ln6PCAYY@!vHGY6Jsxe{E6WRp1u^nh+!#ck zKCJ4TbmnVfpySOq;reQcSE7dqF*T8)j5Cmd+TOJe@GxHTZPySppH-DBV#H8uMbInQRC9QdQ%kgNp zq5NS@fiOn&wBk~0C;2k@>Zvmq8OB#f7fzF2^gJSP!>$|L)X8Xt~f3HbP2a7S})*anSqbb;gcwQ)4+x{lQ3%8;b zggbL^QkT+KG>GTSQ%#-D=Enyr!_O5@9UnMHotaND_8mmhA3S;d+L80>ZN9e^&)xl4 zYfAsH6LjuMFu`ND>CaPfGt9A#= zU(62a22RiTDa#k<%rW+o*DQaXk}7Z=`7%!A`29Vb?yB6Aj+=9N^IXN?vgG-=3$#8J1F?R;1D0jKv2#SN${1!&l8!(Q(~DcC`{;|G8B`WuFgzEj33C#*{lX3(d|dGTRNjpu>+S*# zFIaJEX2)O3NphWQy+jxqxG?c|=^HkWv$as0;v zvf~GkACD`{-2Y3;_x3d@wQ?htrt))2?}i>-egE=jmz_Xcs&?_u8;x=8tg75fg8gx7 z`ri&GFL=x>j0xtRrm$aYb`QZgMEMLhn0z9COVsDe$@#`>0Oa?>Q~R#$*SwcU_cOhg zcvnchPvmORn1aX;wb0i?nOz0mj*SfN9N(>S_;tn1L@7HMqRm^KdZ>m=^$b++H^to< zDPz3G)hYdv)zs?sNFK74ucj`$(JWWfx63%>vYw-vgJw$GX_}ix^mUF$X^ISLDjc!? z+EY|QK5O^8L|tg+>xd8*&WSq6+Gw4;F5O=rW4cxh=f60%m5UWfe}#|)_!VIn*&7b0 zuQe6ejYop7HyMwpzlmG}nT3eep1oime6jk{{R|1?{b>fTPEQQ`3fPVgkIJ7gb21yh zoEBuoLZLXaJeVV_Wko0M#VOf$#!2wQ+T>qr<#TG-A@^{W+62yKG1%I^X=b~nGF7Du zqJyee_n(Z)GNmzbs!&|I%mn5Vv+Fnv7e5z+j{e2DdZ6yO6t?~V+-*r{b#7%@eIB-a z#&brsBUaE$-2C{Vj4>!zpH*;CTQDQ<dTrF*1X{Px{4iGS#$L{ zZsbPNXxQbIB^N^b6KZ!<@E$8&rpHkJqF>8V1J-@tnR$t)gV7>fwe(M5w2QBv4!OyC z(n?+$KL7YE^~xH;=-4mawqI*M?h~b~Hb0MID9t6+;!C9&uDYImXS~wRB7wBwhD^`< zhAWNo;Z>>(y?K*PJpE@oPAyoFr&60q6hgd4K_~hTC{{kEl;AJU`}Wk#mS(|!lr^HN zJb`v;rQag*-ZPA6m3CJ(Pu%TgU%Sy`-obQn`zPYt*qwr@jV>@xlB9jhE1}}H&MX4r zR|j5GkLuryYL9uBrq8LvbT&9DDDnxVK!8M(7^Q*n6W{9*VyJf<>dZtHk0;5oWgMDU z2B@RDk=6S?pH=zPVj$VCP5rb;(kv{pOzM^Acv%`5iysMxoBI-C6;i%#EqO0j9pjVz zSH8N5u4dG-dkaL2cFCR_L%x{HnV*rlSOHhdj$j@2j@8ejCA%>tO;b|!kwGx^Q{GY* zy_l#;QJm57=mlIsa8|LLlMNcmJZCd8EAEOx%PZ;KZZp0 z)Z8v2=_>A-n1T24Tq90>&)9Z3{Mq%>UKY?JIY%BtNvLg^kY~St?^YN7PRnyK*zs8f z>CtagT;yk%BumB;WzHh+_65a^w(Jc%yt{oT_z>I}ZY;3?Q&_R9FTZ@D7H8O?78 zC?@RCWxewZJwGPpz;El~Jj%85CkOU9KRZcL21H(zi> zJ}y7bCo=%KS1!wNu2cN=J>_0ChI1Krr~1q~oGJRu^fL~9fR~$6JVRe=&^O||M#EU0 zS$MRJ<+Zx=S$|r_@mH^oYCygam7~diSc82&1*LK{lL-^e8ww|teREfMr%&ax{0lPq zSHDfw56ErdTNFH}F4nxd?0Cwki1;bG%KnP?kv3}yrz?UKSc8+&*S)V&2m!$zc1&Kv zw}rVY7uoMG5Z`Vf?Kw;OD^w`t&@t-cp-)Ijj-2&;{~OJAU;Z|l%~{>oC7h}Cw9zYu zFW$5R6j#WIX^4}_8Jt^6g@mUN6poRt0>{kj^xo5J@~FT2z`+QygV=D`3d>j!d3hW) zf!abUZgY4mzkX7Cr&nI%@Q6M=va`}rmK=<3Nr(=DPYxqL1?FIZ3>a86JORF?DN{FNi} z`9M@sMy^=$h0OUEivfe~isTW2c{Ngl!i**@4h0J}K4CduX387jlrzHE=MiloDKZNQ zXL@1+V*}bS3kk3vDtTrlZTG|imRh(<=>G7Rs?WJU;(4vu2g=&_@qLJU{)F_`(HqCf zUeH)M-yOL3%A@C=0PUpMB+DdA-|62`lZ-lCI`Z$%y3SCW32IGheL!BV^>Q(Ct+xME zn0DqJWxRMp?%dl0B@dSw7mA#Nf1Yg;>J#aso{@yWb>RELL3E_%?A|?oJ^J2q#-=v9 zS`#C|eWC|?S{80ombp#pINvYS$}cRvArnP8?a@zPTUy0HHc%~k^4n@M=7f<+i4%v8 zbnk51eeHQEq}j)rqNSR*zUczG85wm#dojSy_-M%A8RcM*|1v&WN>p7=Ll!SJE?C~c z9BbpSks@|yxXXW;A{P#D<3@^HI1uXs1e*LqRy3Y}&X5bV@-JguxIr5c6uV+wwnBvd z4??8>1*QHR@UnN1^u}!cUj@8uC5qh&Ou_xV8F2FVx2@lHe{R*>yT;b9xH=mpwjf)d zTkxH&?p<=L#?H?_r@r0$m)%f;@R<#{w{xmtkUc`8VL+(oSmAbj)|E}tcKd6|l$4r%TyQZAjPlB49)u7q;MbNpZ=Wzm` z=+1sn{G1k73N=1^D)~W^O*7U)hEJxcHXD=D^y;)vNMQ7#F`2IF5)0P}r|}i{L8poQ z!N`f8i4ah{f*D(oowlJv(~A;x?j4B*&qUkqU*P)t?dWyZ?yVLBJ#Be<2y_p{wHP`h-t1we+A6`J^%uLNYEWyW7w7N#- zJ=qv-MDSwJ6v$A^aCYvTN@=qHt@rI6&DXlJjo#lg{}AZ>g+(bvh%|+K8t#^!tRACS zBvp`J2D*OyF*nf!nMv?M{bW?HO!|9_O(91n(c=%f`XAdTa&Gs`3~|*JJUyG@wCt3o zW$}zwYX1EPhJ@2|M4o5h;}DeRsJLB5i)F$MZOaT7^LA?Z?}hSSpYnm=k_ScwvdoQ= zCt>-Q=1ipvBxF8`c8qpJzrE2?^xOQwT%x1yS<n zm$sYHVPTbfK*Z3?H1~4Gx!nTxu%k%6T{w`nbEGcbzu`}KkYC>&?BsC^}SWI`w zN771jt&%S-xy}m>oa7WnCr%8W^skp#CAVTp>$l36FnMNeyTr_TN`y_5EGo|XB~?pi zQ1uNHYjbPnq~2Hh_uC>aw4VrjZyduCe~qNtAa70@qk*kElT)e{_TJ(u`O1n1e}vCn zdhfffLZzoI&Z=m9xXJKT!!SMy&iPR!r=3&h*bDYE?DJ98^)e=RenqnD-?;Rq4Sgmt z-ftnd^6g`n3BiRIoOj#aa1~T2+C*NT?^}en(U(T8BF-Oa6p>ra`BpMfwPts;gIO_> z#^)#Zpxx^LUrctm=F|mPlZJshS+*v^Po$u_wm+q1<}RHFdo8BPJxyQEkmNN&o+DMv zoias?%%&tvuJ4?qJcRO*+>fNsl1FY8EBiY&xwyu-4jtBx6L3BMC8LP*3-kSe`((L` zx5bTp3z@GvrxKx39~JS7CjVp+`kwu%5&5`ZyFgCZK0>Tt+r?AP#!XEi_W6|`pyZ#6 z4#=C#;<;X8KQ)e4kNM0HzYlCdUyM#lFW^m-&d*epZB~tj#%HK%KIWuTO0UpZ1jh_3 zk78&ndQ+Hxo||rAo$GJ(i&WbFbRiZne!MN^)9!Rif*L>*8f}~(8+EKm- zmeK!8$adP_Hr=W@X-aUqRsGqVM9)%SR(e`q%ALe83|RVy;Y}veuU!TZXBzohr4uZP z3gDmUU&hmi)JhKpi-a`0Cw8~ls+7O`tLMx+dGV>9^PIXDL&AuyQxDVd|CanqaPFJ7 z;Nt!_);$-w%qv{j>oukVytAx)YOtNj1jgT1|}==F0TB=$H96 zmn~aAy}>>(XSi%wSb#0kvefjD6>#ViGuL~m|JTUPK1=vyB$427e){~g0JXIH!p~2+ zlaIigO;ap|AA9HAn2XM;ZlR0Liu>&0mo1^8FP?uo{k&4<=gAD>22*v7ljqdJ6;FD9 zKH;cA_s;K!aei6A591rs<*yUn^EqxOx^pxt#OvF?+_KFcYs6K55osg($qtLeh1!msC?>(h!#YP0~S;{Xx}| z)^>xOLdTNNRo@YzKbF*KbeEXZB*4DT=izKULxudS>fh=WHZ;llbd*mAO0UuvM~n!)jK9o}!zQp^8;G~4gdsy2Gu1~|kDl}7Ma@@zSGbrZ`U0$hGW7dH>N1hq$%g&ZgCU;K=y; zz3lfL*8;eq5Hzj`&Yy!pc7|jB9rgR)TnnhNEC=Ck!@9{(97PAaUI|T``7Yd)W-0hr z`FG})+pWL9m2d@~f9$IF6k{S*K0PwY?HqQyMEMiTxtI0yWeD?xqvs-{OuA3`H~s8s zNuxP&s^PnhE;Xk|-W^GjWfsad5k7`!*(Z}#f88z#7P58sE^l)%m+w2-N69%veYkaA z?~`$%+6gN&p>HZT=wzY`vtwS522SORd)kc^o|Gi^xPFyRa^cj|y|zjcTJKL`v1u12C@5a0#? z9QyyjBf>TFU${j0;s4M-q{haJ|KI!3kbk1opB*BA<8k*7an9xTMGU}W!%fxyl|!`C z9r^#~`?k}A-yiOmJzN$1NPk>N|L*%K3i>7(yLAFdV~y-US|FTLrvzHhORWT4P+k8E zwSE->_NLQDvtaI>?QT@~yIrik zIRPo}b*!Zc$k@RWU?AWh zj4j9!7%&c|Z)pUw$68=OhE|qFSRAeG@J6yt$<2|hbKJ&?-G$mFNB&JdD1gdt^5JUY zkx$IZ)=A&i2xO>lZf*y%w*uLlVnEimR`yngR^~XQ>}~Z8?SWrRZLJ(kOhNh}b1X1b zR>mNGBMYp(J;n$(taT>YXycFAE7)Qj0an?j`sQ%9slJ=ic*B9?7SrzG;A-LxN8Acv z2TOfRL(D(n@h2*7F6b>P;;yRWb-QIP?3iI?jG==q*4_oAZ)fLVVZGNhZZFAALJ-XB z_6pfe2t15n2w=7CCIqe~9wC$+EG+bGUGS(tfW(efv5S{B<=GY$P`C}8-FoJHwiZ7>fh)PN`_r##m2IezykdGZ&BHn zU>m3)wsG4OstBCy-H>`4@?r;IQ&#V>C^uEXpD|x=1#j}SBp^_2kdTp)Eym6cV~67^ zD?_Y4Zm~IG?M*@Aw))nlSFNsNEODYm4OqGudk`R;0oh`UF~{l~nB%km9|^mmfws^? zqJVO^eIr_EX3mQNeAyq8wk((wNQ^F8!}mJDv1RV)q7G5WS3tfeV#(cokk$OvPHHQB9o zx!1?OQ|luBB*O5q*<)7s&;$TB+}a>XOKS&vkhQ+8z6Hh}V+-&ez*d%4_8>=nbF2}L z1$Qm#omg!w>Kz2!r13TZ@uqvzEZQO(42Cb**6k!b<^#}#X@g|+4X@*r5Ef9T&cL$R zfiTt*1c)C?`+vgokJQ_=(zeh-;f`^3uZcZ0fSi>*uu#w87VWwg2c)2+rLmQ*h5moE zpEhZ>y&^Vfw!>cAl0MtoVS_J`+jahIP(e2>&A-P&AUJ_sIRv^xOKzPn?Qr&q5yn{G z!F+xC9WVg70Y0$ZL%^(GwB5y=+X5AD*6~n6;w*yQ>DXwn^vI4ZL1=e+) ztRQPEJ3B0awA+EqCVjVwx5<;+GU-2K2g9|s8#`Q8e4doU@ubQ+!Sq2^mKd;|J;oXY zm`;{<#(=R0@Bzrm$r4yjrdaC@lMg4n?Lf8|L##EHkXg6I(&hlRskzA@+sX)U0GmF= z-!qN^O70o}a+eRWp(+9L!nHvF4}%OG41n`SVB#ID*X=m~ML?I^10VW!1hy$5p||O} ziRTVAy34?T;^7Iy$&KB3;;Ir78iA9T4t6{2PCSE|0IBr>@8r!LOJ_Inwj8nlK)gK^ z5I{VnHb~9Z3ZR-J7T`y$InERW*2%x0$dgK6Y0l3CE`{z91GyL5<;L`2g(0aj5a}jK}WiEoW_BQlz zrGYhsb5y|Vjtbb`3Jf?Z;4Mc5{I{b5fY%)rus#^)sDQ1E!CQ_BcxyT~+PDDH+S|pz z^=7i|M}V~O4Dd~t09VWu0tK4iG}FM_W*Qi0rh!dxW|}>2rJDn0n$x%hJ#P0Of|KLaC%9#WB0^S3c~@kU!tJ1LAm{2e5=SWh~# ztMKOb&eqKBC~S$NGfo`f`hT@UfvM2pidy@EeUFfO*3S@xRxk9k3knrQNP>kzgmBgavO)SR6ICmh@iL zH-+VThdApDw^BE4Gob3WZAM7V9W#lO1MAyM_^WDj>j&4m-KO`C699jE{{&)V({Ep| zu<4wGwD$J1LBLMs&RxHqN(Z-7W(VxSt*Z>s&Qd!yfx`OM9bkH#H^e=g2!e7#5uCuj z-FZ`cduv`Uu65|Te8L*qaa!4$T-Y#|uWr}_^41tjO^mfQ;7nSAgd6~}fs`=7W4@b4 zwUC3oDPYo^m*)UkbAT`$AWIIA=K2@l&kcw<2M7zmH(Hg(xHwta0()QQH~tm|xWsq4P8 zR~HY4AXrCGC>l+`e}JqfgdrjLw1)!uM)CO`cw(3ve{DfwNL<#?-MGLZIJX232FF=J zcrY|BmT)%=0YwqQ5CrQDir^unDUzFD-hjMl1nZ3(iiQH>c6YxhC>kFIq`AU5^#7(D z&idX}4#?n3&<8gZg-aB>yBr)vAg=&fjKb%uJz+2&!anw@3q#|Q`tItN2TedzAafiF zNFcYn9B}%?O^7p`aJ+C7PL1#C14x#KJ1WD2!Exzh@n8@F-sMKXQTVinaRU=fP#2B- z9|PkdlFB(qZ8^Heu!2mK7*iw7p2b2Tir0~WI4^FaLnYE(r7%Kq>+o9R(OB1bx8J-1u}s!JxRK^xe1s zwiF%=*uUb&?LhA=2f*O??Ex?Zz7Gb#Q22H+0OP?$0`6`PxaNh&8&GZ-fvpF?2>fIK z2FLen0T|$%67+$_x0Qi%d&ob)y(AbfoEzWQ1*|nVF1BL#IDmaA!ny=DCQz3Lcc`|z zE&^~O2w>~c<#^@b_`?A4G0GOnDq~$S>jxIV5fhh^6%fn;!-<{Em_=MP5&!^j1^~c0hn>B?t^N8b2hcYX O0Xf3TDk?8_ 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..ac66c1fb2 --- /dev/null +++ b/packages/token-distribution/contracts/L2GraphTokenLockManager.sol @@ -0,0 +1,159 @@ +// 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..7c687b48d --- /dev/null +++ b/packages/token-distribution/contracts/MinimalProxyFactory.sol @@ -0,0 +1,79 @@ +// 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..779cf5b36 --- /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 } from 'hardhat-deploy/types' + +const { parseEther } = utils + +const logger = consola.create({}) + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deploy } = hre.deployments + 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..66cbc3af9 --- /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 } 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 } = hre.deployments + 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..53a9f7f5c --- /dev/null +++ b/packages/token-distribution/deploy/3_l2_wallet.ts @@ -0,0 +1,27 @@ +import consola from 'consola' +import '@nomiclabs/hardhat-ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { DeployFunction } from 'hardhat-deploy/types' + +import { getDeploymentName } from './lib/utils' + + +const logger = consola.create({}) + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deploy } = hre.deployments + 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..b8fb04473 --- /dev/null +++ b/packages/token-distribution/deploy/4_l1_transfer_tool.ts @@ -0,0 +1,79 @@ +import consola from 'consola' +import { utils } from 'ethers' + +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..5572345da --- /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 } 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 } = hre.deployments + 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..659a104a4 --- /dev/null +++ b/packages/token-distribution/deploy/6_l2_transfer_tool.ts @@ -0,0 +1,69 @@ +import consola from 'consola' +import { utils } from 'ethers' + +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) { + const { deployer } = await hre.getNamedAccounts() + + // -- 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..7330f4e55 --- /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 +} + +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'] +} 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/hardhat.config.ts b/packages/token-distribution/hardhat.config.ts new file mode 100644 index 000000000..4fa7a9cb8 --- /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 + +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: { + //url: process.env.ETHERSCAN_API_URL, + 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..778865ec0 --- /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 { utils, BigNumber, Event, ContractTransaction, ContractReceipt, Contract, ContractFactory } 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 +} + +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 = [] + 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) { + 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..d4ca09b25 --- /dev/null +++ b/packages/token-distribution/ops/delete.ts @@ -0,0 +1,88 @@ +import { task } from 'hardhat/config' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import { prettyEnv, askConfirm, 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..a0a024a37 --- /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, providers } from 'ethers' +import { HardhatRuntimeEnvironment } from 'hardhat/types' +import CoinGecko from 'coingecko-api' +import { Block } from '@ethersproject/abstract-provider' +import * as GraphClient from '../.graphclient' +import { + execute, + GraphNetworkDocument, + GraphNetworkQuery, + TokenLockWalletsDocument, + TokenLockWalletsQuery, + CuratorWalletsDocument, + CuratorWalletsQuery, + GraphAccountQuery, + GraphAccountDocument, +} 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 }) + + contracts.map(async (contract) => { + 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)}%):`, + formatRoundGRT(this.totalAvailable), + ) + console.log(`- Free (${this.totalFree.mul(100).div(this.totalManaged)}%):`, formatRoundGRT(this.totalFree)) + console.log( + `-- Released (${this.totalFree.gt(0) ? this.totalReleased.mul(100).div(this.totalFree) : 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) + revocableWallets.map(async (wallet) => { + 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[] = [] + allWallets.map(async (wallet) => { + 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..159bd9a21 --- /dev/null +++ b/packages/token-distribution/ops/tx-builder.ts @@ -0,0 +1,31 @@ +import fs from 'fs' +import path from 'path' + +export class TxBuilder { + contents: any + 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: any) { + 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..85475bd66 --- /dev/null +++ b/packages/token-distribution/package.json @@ -0,0 +1,84 @@ +{ + "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:fix": "yarn run lint:ts:fix && yarn run lint:sol:fix", + "lint:ts": "eslint '*/**/*.{js,ts}'", + "lint:ts:fix": "eslint '*/**/*.{js,ts}' --fix", + "lint:sol": "solhint './contracts/**/*.sol'", + "lint:sol:fix": "yarn prettier:sol && solhint --fix './contracts/**/*.sol'", + "prettier": "yarn run prettier:ts && yarn run prettier:sol", + "prettier:ts": "prettier --write 'test/**/*.ts'", + "prettier:sol": "prettier --write 'contracts/**/*.sol'", + "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", + "@typescript-eslint/eslint-plugin": "^5.20.0", + "@typescript-eslint/parser": "^5.20.0", + "chai": "^4.2.0", + "coingecko-api": "^1.0.10", + "consola": "^2.15.0", + "dotenv": "^16.0.0", + "eslint": "^8.13.0", + "eslint-config-prettier": "^8.5.0", + "eslint-config-standard": "^16.0.3", + "eslint-plugin-import": "^2.22.0", + "eslint-plugin-mocha-no-only": "^1.1.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^4.0.0", + "eslint-plugin-promise": "^6.0.0", + "eslint-plugin-standard": "5.0.0", + "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": "^2.1.1", + "prettier-plugin-solidity": "^1.0.0-alpha.56", + "solhint": "^3.3.7", + "solhint-plugin-prettier": "^0.0.5", + "ts-node": "^10.9.1", + "typechain": "^5.0.0", + "typescript": "^4.0.2" + } +} 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..be3179e72 --- /dev/null +++ b/packages/token-distribution/test/distributor.test.ts @@ -0,0 +1,201 @@ +import { expect } from 'chai' +import { deployments } from 'hardhat' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { GraphTokenDistributor } from '../build/typechain/contracts/GraphTokenDistributor' + +import { getContract, getAccounts, toGRT, Account } from './network' + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const { deploy } = deployments + 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..73915e676 --- /dev/null +++ b/packages/token-distribution/test/l1TokenLockTransferTool.test.ts @@ -0,0 +1,674 @@ +import { BigNumber, constants, Signer } from 'ethers' +import { expect } from 'chai' +import { deployments, ethers, upgrades } from 'hardhat' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { GraphTokenLockWallet } from '../build/typechain/contracts/GraphTokenLockWallet' +import { GraphTokenLockManager } from '../build/typechain/contracts/GraphTokenLockManager' +import { StakingMock } from '../build/typechain/contracts/StakingMock' +import { L1TokenGatewayMock } from '../build/typechain/contracts/L1TokenGatewayMock' +import { L1GraphTokenLockTransferTool } from '../build/typechain/contracts/L1GraphTokenLockTransferTool' + +import { L1GraphTokenLockTransferTool__factory } from '../build/typechain/contracts/factories/L1GraphTokenLockTransferTool__factory' +import { Staking__factory } from '@graphprotocol/contracts/dist/types/factories/Staking__factory' + +import { defaultInitArgs, Revocability, TokenLockParameters } from './config' +import { getAccounts, getContract, toGRT, Account, toBN } from './network' +import { defaultAbiCoder, hexValue, keccak256, parseEther } from 'ethers/lib/utils' +import { advanceTimeAndBlock } from './network' + +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 } = deployments + 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 as L1GraphTokenLockTransferTool, + } +}) + +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..9db78d426 --- /dev/null +++ b/packages/token-distribution/test/l2TokenLockManager.test.ts @@ -0,0 +1,459 @@ +import { constants, Wallet } from 'ethers' +import { expect } from 'chai' +import { deployments, ethers } from 'hardhat' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { L2GraphTokenLockWallet } from '../build/typechain/contracts/L2GraphTokenLockWallet' +import { L2GraphTokenLockManager } from '../build/typechain/contracts/L2GraphTokenLockManager' +import { StakingMock } from '../build/typechain/contracts/StakingMock' +import { Staking__factory } from '@graphprotocol/contracts/dist/types/factories/Staking__factory' + +import { defaultInitArgs, Revocability, TokenLockParameters } from './config' +import { advanceTimeAndBlock, getAccounts, getContract, toGRT, Account } from './network' +import { defaultAbiCoder, keccak256 } from 'ethers/lib/utils' +import { Staking } from '@graphprotocol/contracts' + +const { AddressZero } = constants + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const { deploy } = deployments + 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 } = deployments + + 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..38b5f79d6 --- /dev/null +++ b/packages/token-distribution/test/l2TokenLockTransferTool.test.ts @@ -0,0 +1,262 @@ +import { constants } from 'ethers' +import { expect } from 'chai' +import { deployments, ethers, upgrades } from 'hardhat' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { L2GraphTokenLockWallet } from '../build/typechain/contracts/L2GraphTokenLockWallet' +import { L2GraphTokenLockManager } from '../build/typechain/contracts/L2GraphTokenLockManager' +import { L2TokenGatewayMock } from '../build/typechain/contracts/L2TokenGatewayMock' +import { L2GraphTokenLockTransferTool } from '../build/typechain/contracts/L2GraphTokenLockTransferTool' +import { L2GraphTokenLockTransferTool__factory } from '../build/typechain/contracts/factories/L2GraphTokenLockTransferTool__factory' + +import { defaultInitArgs, TokenLockParameters } from './config' +import { getAccounts, getContract, toGRT, Account, toBN } from './network' +import { defaultAbiCoder, keccak256 } from 'ethers/lib/utils' + +const { AddressZero } = constants + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const { deploy } = deployments + 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 as L2GraphTokenLockTransferTool, + 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..08fa82af8 --- /dev/null +++ b/packages/token-distribution/test/network.ts @@ -0,0 +1,95 @@ +import { providers, utils, BigNumber, Contract, Signer } 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 = [] + 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', []) +} + +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 + if (target.lt(currentBlock)) throw Error(`Target block #(${target}) is lower than current block #(${currentBlock})`) + 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]) +} + +export const advanceTimeAndBlock = async (time: number): Promise => { + await advanceTime(time) + await advanceBlock() + return latestBlockNum() +} + +export const evmSnapshot = async (): Promise => provider().send('evm_snapshot', []) +export const evmRevert = async (id: number): Promise => provider().send('evm_revert', [id]) diff --git a/packages/token-distribution/test/tokenLock.test.ts b/packages/token-distribution/test/tokenLock.test.ts new file mode 100644 index 000000000..aa9b652da --- /dev/null +++ b/packages/token-distribution/test/tokenLock.test.ts @@ -0,0 +1,770 @@ +import { expect } from 'chai' +import { constants, BigNumber } from 'ethers' +import { deployments } from 'hardhat' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { GraphTokenLockSimple } from '../build/typechain/contracts/GraphTokenLockSimple' + +import { createScheduleScenarios, defaultInitArgs, TokenLockParameters, Revocability } from './config' +import { advanceTimeAndBlock, getAccounts, getContract, toBN, toGRT, Account } from './network' + +const { AddressZero } = constants + +// Fixture +const setupTest = deployments.createFixture(async ({ deployments }) => { + const { deploy } = deployments + 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) + 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', async 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(async 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()', async 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 = 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..3de4e769b --- /dev/null +++ b/packages/token-distribution/test/tokenLockWallet.test.ts @@ -0,0 +1,377 @@ +import { constants, BigNumber, Wallet } from 'ethers' +import { expect } from 'chai' +import { deployments, ethers } from 'hardhat' + +import '@nomiclabs/hardhat-ethers' +import 'hardhat-deploy' + +import { GraphTokenMock } from '../build/typechain/contracts/GraphTokenMock' +import { GraphTokenLockWallet } from '../build/typechain/contracts/GraphTokenLockWallet' +import { GraphTokenLockManager } from '../build/typechain/contracts/GraphTokenLockManager' +import { StakingMock } from '../build/typechain/contracts/StakingMock' + +import { Staking__factory } from '@graphprotocol/contracts/dist/types/factories/Staking__factory' + +import { defaultInitArgs, Revocability, TokenLockParameters } from './config' +import { advanceTimeAndBlock, getAccounts, getContract, toGRT, Account, randomHexBytes, advanceBlocks } from './network' + +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 } = deployments + 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 + + async function getState(tokenLock) { + 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), + releasableAmount: await tokenLock.releasableAmount(), + releasedAmount: await tokenLock.releasedAmount(), + revokedAmount: await tokenLock.revokedAmount(), + surplusAmount: await tokenLock.surplusAmount(), + managedAmount: await tokenLock.managedAmount(), + usedAmount: await tokenLock.usedAmount(), + } + } + + 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 } = deployments + + 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..16dea551a --- /dev/null +++ b/packages/token-distribution/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "lib": ["ES2020", "dom"], + "module": "commonjs", + "moduleResolution": "node", + "target": "ES2020", + "outDir": "dist", + "resolveJsonModule": true, + "esModuleInterop": true + }, + "exclude": ["dist", "node_modules"], + "files": [ + "./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 11963d3c8..38a28ce3c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -24,6 +24,16 @@ __metadata: languageName: node linkType: hard +"@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.0.0, @arbitrum/sdk@npm:^3.1.12": version: 3.1.13 resolution: "@arbitrum/sdk@npm:3.1.13" @@ -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" @@ -97,1870 +159,3533 @@ __metadata: 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 - 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/code-frame@npm:^7.23.5": + version: 7.23.5 + resolution: "@babel/code-frame@npm:7.23.5" dependencies: - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/highlight": "npm:^7.23.4" chalk: "npm:^2.4.2" - js-tokens: "npm:^4.0.0" - checksum: fbff9fcb2f5539289c3c097d130e852afd10d89a3a08ac0b5ebebbc055cc84a4bcc3dcfed463d488cde12dd0902ef1858279e31d7349b2e8cee43913744bda33 - languageName: node - linkType: hard - -"@babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.5.5": - version: 7.23.8 - resolution: "@babel/runtime@npm:7.23.8" - dependencies: - regenerator-runtime: "npm:^0.14.0" - checksum: ba5e8fbb32ef04f6cab5e89c54a0497c2fde7b730595cc1af93496270314f13ff2c6a9360fdb2f0bdd4d6b376752ce3cf85642bd6b876969a6a62954934c2df8 + checksum: a10e843595ddd9f97faa99917414813c06214f4d9205294013e20c70fbdf4f943760da37dec1d998bf3e6fc20fa2918a47c0e987a7e458663feb7698063ad7c6 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/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 -"@chainsafe/persistent-merkle-tree@npm:^0.4.2": - version: 0.4.2 - resolution: "@chainsafe/persistent-merkle-tree@npm:0.4.2" +"@babel/core@npm:^7.14.0": + version: 7.23.9 + resolution: "@babel/core@npm:7.23.9" dependencies: - "@chainsafe/as-sha256": "npm:^0.3.1" - checksum: 9533e478a1a990e8cf8710a2eeb84c6f08c7b61726a43dbe2165316256839c29a2ff17923bce5e5effec446d832de8b0a5bc896ef5db80bce059af5d1bd20d8d + "@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/persistent-merkle-tree@npm:^0.5.0": - version: 0.5.0 - resolution: "@chainsafe/persistent-merkle-tree@npm:0.5.0" +"@babel/generator@npm:^7.14.0, @babel/generator@npm:^7.23.6": + version: 7.23.6 + resolution: "@babel/generator@npm:7.23.6" dependencies: - "@chainsafe/as-sha256": "npm:^0.3.1" - checksum: 73c7a7536f49aceab61870fcc1dafef8a8be2ae0bfff2614846bb4b57a21939da75bca7bc5d1959cd312a5133be0acaf0e30fb323410c57592e9ec384758efe0 + "@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/ssz@npm:^0.10.0": - version: 0.10.2 - resolution: "@chainsafe/ssz@npm:0.10.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" - "@chainsafe/persistent-merkle-tree": "npm:^0.5.0" - checksum: be427eba9f9c4a542326f9f3c20eb704c1c2500c4f124ba18febf6ffd5bb7bd5755228d99326bf6c4e4d969daa4b6ff2efb743688ec36ef86f20c0c673c0e967 + "@babel/types": "npm:^7.22.5" + checksum: 5a80dc364ddda26b334bbbc0f6426cab647381555ef7d0cd32eb284e35b867c012ce6ce7d52a64672ed71383099c99d32765b3d260626527bb0e3470b0f58e45 languageName: node linkType: hard -"@chainsafe/ssz@npm:^0.9.2": - version: 0.9.4 - resolution: "@chainsafe/ssz@npm:0.9.4" +"@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" - "@chainsafe/persistent-merkle-tree": "npm:^0.4.2" - case: "npm:^1.6.3" - checksum: 4ce4b867c60dbee98772fe075037c7ef9a7894f97a4fb04f3cfd57e11fa683b8c23a4d80b53592d10fbd4e2abac43c9099181cfaee587619366f49091b9e5fcb + "@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 -"@changesets/apply-release-plan@npm:^7.0.0": - version: 7.0.0 - resolution: "@changesets/apply-release-plan@npm:7.0.0" +"@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: - "@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 + "@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 -"@changesets/assemble-release-plan@npm:^6.0.0": - version: 6.0.0 - resolution: "@changesets/assemble-release-plan@npm:6.0.0" - dependencies: - "@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 +"@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 -"@changesets/changelog-git@npm:^0.2.0": - version: 0.2.0 - resolution: "@changesets/changelog-git@npm:0.2.0" +"@babel/helper-function-name@npm:^7.23.0": + version: 7.23.0 + resolution: "@babel/helper-function-name@npm:7.23.0" dependencies: - "@changesets/types": "npm:^6.0.0" - checksum: d94df555656ac4ac9698d87a173b1955227ac0f1763d59b9b4d4f149ab3f879ca67603e48407b1dfdadaef4e7882ae7bbc7b7be160a45a55f05442004bdc61bd + "@babel/template": "npm:^7.22.15" + "@babel/types": "npm:^7.23.0" + checksum: d771dd1f3222b120518176733c52b7cadac1c256ff49b1889dbbe5e3fed81db855b8cc4e40d949c9d3eae0e795e8229c1c8c24c0e83f27cfa6ee3766696c6428 languageName: node linkType: hard -"@changesets/cli@npm:^2.27.1": - version: 2.27.1 - resolution: "@changesets/cli@npm:2.27.1" +"@babel/helper-hoist-variables@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-hoist-variables@npm:7.22.5" 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 + "@babel/types": "npm:^7.22.5" + checksum: 60a3077f756a1cd9f14eb89f0037f487d81ede2b7cfe652ea6869cd4ec4c782b0fb1de01b8494b9a2d2050e3d154d7d5ad3be24806790acfb8cbe2073bf1e208 languageName: node linkType: hard -"@changesets/config@npm:^3.0.0": - version: 3.0.0 - resolution: "@changesets/config@npm:3.0.0" +"@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: - "@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 + "@babel/types": "npm:^7.23.0" + checksum: b810daddf093ffd0802f1429052349ed9ea08ef7d0c56da34ffbcdecbdafac86f95bdea2fe30e0e0e629febc7dd41b56cb5eacc10d1a44336d37b755dac31fa4 languageName: node linkType: hard -"@changesets/errors@npm:^0.2.0": - version: 0.2.0 - resolution: "@changesets/errors@npm:0.2.0" +"@babel/helper-module-imports@npm:^7.22.15": + version: 7.22.15 + resolution: "@babel/helper-module-imports@npm:7.22.15" dependencies: - extendable-error: "npm:^0.1.5" - checksum: f2757c752ab04e9733b0dfd7903f1caf873f9e603794c4d9ea2294af4f937c73d07273c24be864ad0c30b6a98424360d5b96a6eab14f97f3cf2cbfd3763b95c1 + "@babel/types": "npm:^7.22.15" + checksum: 4e0d7fc36d02c1b8c8b3006dfbfeedf7a367d3334a04934255de5128115ea0bafdeb3e5736a2559917f0653e4e437400d54542da0468e08d3cbc86d3bbfa8f30 languageName: node linkType: hard -"@changesets/get-dependents-graph@npm:^2.0.0": - version: 2.0.0 - resolution: "@changesets/get-dependents-graph@npm:2.0.0" +"@babel/helper-module-transforms@npm:^7.23.3": + version: 7.23.3 + resolution: "@babel/helper-module-transforms@npm:7.23.3" dependencies: - "@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 + "@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 -"@changesets/get-release-plan@npm:^4.0.0": - version: 4.0.0 - resolution: "@changesets/get-release-plan@npm:4.0.0" +"@babel/helper-optimise-call-expression@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-optimise-call-expression@npm:7.22.5" dependencies: - "@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 + "@babel/types": "npm:^7.22.5" + checksum: 31b41a764fc3c585196cf5b776b70cf4705c132e4ce9723f39871f215f2ddbfb2e28a62f9917610f67c8216c1080482b9b05f65dd195dae2a52cef461f2ac7b8 languageName: node linkType: hard -"@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 +"@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 -"@changesets/git@npm:^3.0.0": - version: 3.0.0 - resolution: "@changesets/git@npm:3.0.0" +"@babel/helper-replace-supers@npm:^7.22.20": + version: 7.22.20 + resolution: "@babel/helper-replace-supers@npm:7.22.20" dependencies: - "@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 + "@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 -"@changesets/logger@npm:^0.1.0": - version: 0.1.0 - resolution: "@changesets/logger@npm:0.1.0" +"@babel/helper-simple-access@npm:^7.22.5": + version: 7.22.5 + resolution: "@babel/helper-simple-access@npm:7.22.5" dependencies: - chalk: "npm:^2.1.0" - checksum: b40365a4e62be4bf7a75c5900e8f95b1abd8fb9ff9f2cf71a7b567532377ddd5490b0ee1d566189a91e8c8250c9e875d333cfb3e44a34c230a11fd61337f923e + "@babel/types": "npm:^7.22.5" + checksum: f0cf81a30ba3d09a625fd50e5a9069e575c5b6719234e04ee74247057f8104beca89ed03e9217b6e9b0493434cedc18c5ecca4cea6244990836f1f893e140369 languageName: node linkType: hard -"@changesets/parse@npm:^0.4.0": - version: 0.4.0 - resolution: "@changesets/parse@npm:0.4.0" +"@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: - "@changesets/types": "npm:^6.0.0" - js-yaml: "npm:^3.13.1" - checksum: 8e76f8540aceb2263eb76c97f027c1990fc069bf275321ad0aabf843cb51bc6711b13118eda35c701a30a36d26f48e75f7afc14e9a5c863f8a98091021fd5d61 + "@babel/types": "npm:^7.22.5" + checksum: ab7fa2aa709ab49bb8cd86515a1e715a3108c4bb9a616965ba76b43dc346dee66d1004ccf4d222b596b6224e43e04cbc5c3a34459501b388451f8c589fbc3691 languageName: node linkType: hard -"@changesets/pre@npm:^2.0.0": - version: 2.0.0 - resolution: "@changesets/pre@npm:2.0.0" +"@babel/helper-split-export-declaration@npm:^7.22.6": + version: 7.22.6 + resolution: "@babel/helper-split-export-declaration@npm:7.22.6" dependencies: - "@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 + "@babel/types": "npm:^7.22.5" + checksum: d83e4b623eaa9622c267d3c83583b72f3aac567dc393dda18e559d79187961cb29ae9c57b2664137fc3d19508370b12ec6a81d28af73a50e0846819cb21c6e44 languageName: node linkType: hard -"@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 +"@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 -"@changesets/types@npm:^4.0.1": - version: 4.1.0 - resolution: "@changesets/types@npm:4.1.0" - checksum: a372ad21f6a1e0d4ce6c19573c1ca269eef1ad53c26751ad9515a24f003e7c49dcd859dbb1fedb6badaf7be956c1559e8798304039e0ec0da2d9a68583f13464 +"@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 -"@changesets/types@npm:^6.0.0": - version: 6.0.0 - resolution: "@changesets/types@npm:6.0.0" - checksum: e755f208792547e3b9ece15ce4da22466267da810c6fd87d927a1b8cec4d7fb7f0eea0d1a7585747676238e3e4ba1ffdabe016ccb05cfa537b4e4b03ec399f41 +"@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 -"@changesets/write@npm:^0.3.0": - version: 0.3.0 - resolution: "@changesets/write@npm:0.3.0" +"@babel/helpers@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/helpers@npm:7.23.9" dependencies: - "@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 + "@babel/template": "npm:^7.23.9" + "@babel/traverse": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: f69fd0aca96a6fb8bd6dd044cd8a5c0f1851072d4ce23355345b9493c4032e76d1217f86b70df795e127553cf7f3fcd1587ede9d1b03b95e8b62681ca2165b87 languageName: node linkType: hard -"@colors/colors@npm:1.5.0": - version: 1.5.0 - resolution: "@colors/colors@npm:1.5.0" - checksum: eb42729851adca56d19a08e48d5a1e95efd2a32c55ae0323de8119052be0510d4b7a1611f2abcbf28c044a6c11e6b7d38f99fccdad7429300c37a8ea5fb95b44 +"@babel/highlight@npm:^7.10.4, @babel/highlight@npm:^7.23.4": + version: 7.23.4 + resolution: "@babel/highlight@npm:7.23.4" + dependencies: + "@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 -"@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/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/cli@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/cli@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: - "@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-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/config-conventional@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/config-conventional@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: - conventional-changelog-conventionalcommits: "npm:^7.0.2" - checksum: 13977d8c9cbac31c172ead77c36da5fd88c980438a9811e2b5447f994442200daf8d2d37c5ffef9f5b6afef100513a2ac1e3ec94ba667d7a62fce117e57a16b1 + "@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 -"@commitlint/config-validator@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/config-validator@npm:18.4.3" +"@babel/plugin-syntax-class-properties@npm:^7.0.0": + version: 7.12.13 + resolution: "@babel/plugin-syntax-class-properties@npm:7.12.13" dependencies: - "@commitlint/types": "npm:^18.4.3" - ajv: "npm:^8.11.0" - checksum: 8e6f3130a2e9c17c08276fc81b16e70320af27718bfdfc954e5a591538a23f9510bbbf61f60499d5e09488f112df9400730f065c7309006a9e9da7bd1d371385 + "@babel/helper-plugin-utils": "npm:^7.12.13" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 95168fa186416195280b1264fb18afcdcdcea780b3515537b766cb90de6ce042d42dd6a204a39002f794ae5845b02afb0fd4861a3308a861204a55e68310a120 languageName: node linkType: hard -"@commitlint/ensure@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/ensure@npm:18.4.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: - "@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/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8a5e1e8b6a3728a2c8fe6d70c09a43642e737d9c0485e1b041cd3a6021ef05376ec3c9137be3b118c622ba09b5770d26fdc525473f8d06d4ab9e46de2783dd0a 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/plugin-syntax-import-assertions@npm:^7.20.0": + version: 7.23.3 + resolution: "@babel/plugin-syntax-import-assertions@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 7db8b59f75667bada2293353bb66b9d5651a673b22c72f47da9f5c46e719142481601b745f9822212fd7522f92e26e8576af37116f85dae1b5e5967f80d0faab languageName: node linkType: hard -"@commitlint/format@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/format@npm:18.4.3" +"@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: - "@commitlint/types": "npm:^18.4.3" - chalk: "npm:^4.1.0" - checksum: c2ed05e17f2038af79b39ec0d5bd74d42c2ddd9da4eee22ca372414625084b34f69b24e9372c00a3eb061364a258e1a6eb43f9def38ef6e7995606459d900f15 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 563bb7599b868773f1c7c1d441ecc9bc53aeb7832775da36752c926fc402a1fa5421505b39e724f71eb217c13e4b93117e081cac39723b0e11dac4c897f33c3e languageName: node linkType: hard -"@commitlint/is-ignored@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/is-ignored@npm:18.4.3" +"@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: - "@commitlint/types": "npm:^18.4.3" - semver: "npm:7.5.4" - checksum: 9b2456e0b31656eb1c2828d6a4c0ec12815bfb88e734bc673315a08a6ef5b19e96ecd0cc925d88b797bafe4c09a3aca7d5841c02f8e5de4cc88473bbfba1a275 + "@babel/helper-plugin-utils": "npm:^7.8.0" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: ee1eab52ea6437e3101a0a7018b0da698545230015fc8ab129d292980ec6dff94d265e9e90070e8ae5fed42f08f1622c14c94552c77bcac784b37f503a82ff26 languageName: node linkType: hard -"@commitlint/lint@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/lint@npm:18.4.3" +"@babel/plugin-transform-arrow-functions@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-arrow-functions@npm:7.23.3" 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/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: b128315c058f5728d29b0b78723659b11de88247ea4d0388f0b935cddf60a80c40b9067acf45cbbe055bd796928faef152a09d9e4a0695465aca4394d9f109ca languageName: node linkType: hard -"@commitlint/load@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/load@npm:18.4.3" +"@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: - "@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/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 82c12a11277528184a979163de7189ceb00129f60dd930b0d5313454310bf71205f302fb2bf0430247161c8a22aaa9fb9eec1459f9f7468206422c191978fd59 languageName: node linkType: hard -"@commitlint/message@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/message@npm:18.4.3" - checksum: 24b373d5c99230351a31294e974ee338cbac45094c66a6ba9ce00357783f7ebb250fc169fcdd815c8d510951757119fbd1329e7ab9e3097d3e732768d3d93787 +"@babel/plugin-transform-block-scoping@npm:^7.0.0": + version: 7.23.4 + resolution: "@babel/plugin-transform-block-scoping@npm:7.23.4" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 83006804dddf980ab1bcd6d67bc381e24b58c776507c34f990468f820d0da71dba3697355ca4856532fa2eeb2a1e3e73c780f03760b5507a511cbedb0308e276 languageName: node linkType: hard -"@commitlint/parse@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/parse@npm:18.4.3" +"@babel/plugin-transform-classes@npm:^7.0.0": + version: 7.23.8 + resolution: "@babel/plugin-transform-classes@npm:7.23.8" + dependencies: + "@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 + +"@babel/plugin-transform-computed-properties@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-computed-properties@npm:7.23.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-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 -"@commitlint/read@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/read@npm:18.4.3" +"@babel/plugin-transform-destructuring@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-destructuring@npm:7.23.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-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 717e9a62c1b0c93c507f87b4eaf839ec08d3c3147f14d74ae240d8749488d9762a8b3950132be620a069bde70f4b3e4ee9867b226c973fcc40f3cdec975cde71 languageName: node linkType: hard -"@commitlint/resolve-extends@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/resolve-extends@npm:18.4.3" +"@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: - "@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/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 -"@commitlint/rules@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/rules@npm:18.4.3" +"@babel/plugin-transform-for-of@npm:^7.0.0": + version: 7.23.6 + resolution: "@babel/plugin-transform-for-of@npm:7.23.6" 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-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 -"@commitlint/to-lines@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/to-lines@npm:18.4.3" - checksum: a163a647ebcdc9fb8a84f3406f92fde78b90cc73146c367367806d52022c6b6219b78f5b0afea0faab357f95b9e311822bc9309a0148fd31f30bdb77bfcfd84a +"@babel/plugin-transform-function-name@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-function-name@npm:7.23.3" + dependencies: + "@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 -"@commitlint/top-level@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/top-level@npm:18.4.3" +"@babel/plugin-transform-literals@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-literals@npm:7.23.3" dependencies: - find-up: "npm:^5.0.0" - checksum: 69a75878a18ba812e12be899c3b032c1067d093261e7c622f18a3110bc83483d75fa9c2a589086590a9896d389b407cc58d324803821c314bf952912f57b0095 + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 8292106b106201464c2bfdd5c014fe6a9ca1c0256eb0a8031deb20081e21906fe68b156186f77d993c23eeab6d8d6f5f66e8895eec7ed97ce6de5dbcafbcd7f4 languageName: node linkType: hard -"@commitlint/types@npm:^18.4.3": - version: 18.4.3 - resolution: "@commitlint/types@npm:18.4.3" +"@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: - chalk: "npm:^4.1.0" - checksum: 07cbc4b5eb813052401d9e332c0dadca7864cd22eddd06edb6afd1da212243d505c4429ce100012c4086ea99d0f4a4086382fc88e3e662c6577e69d638c3903e + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 687f24f3ec60b627fef6e87b9e2770df77f76727b9d5f54fa4c84a495bb24eb4a20f1a6240fa22d339d45aac5eaeb1b39882e941bfd00cf498f9c53478d1ec88 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-transform-modules-commonjs@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-modules-commonjs@npm:7.23.3" dependencies: - "@jridgewell/trace-mapping": "npm:0.3.9" - checksum: 05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 + "@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 -"@dabh/diagnostics@npm:^2.0.2": - version: 2.0.3 - resolution: "@dabh/diagnostics@npm:2.0.3" +"@babel/plugin-transform-object-super@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-object-super@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" + "@babel/helper-replace-supers": "npm:^7.22.20" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a6856fd8c0afbe5b3318c344d4d201d009f4051e2f6ff6237ff2660593e93c5997a58772b13d639077c3e29ced3440247b29c496cd77b13af1e7559a70009775 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-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: - "@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: a8d4cbe0f6ba68d158f5b4215c63004fc37a1fdc539036eb388a9792017c8496ea970a1932ccb929308f61e53dc56676ed01d8df6f42bc0a85c7fd5ba82482b7 languageName: node linkType: hard -"@ensdomains/ens@npm:^0.4.4": - version: 0.4.5 - resolution: "@ensdomains/ens@npm:0.4.5" +"@babel/plugin-transform-property-literals@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-property-literals@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: b2549f23f90cf276c2e3058c2225c3711c2ad1c417e336d3391199445a9776dd791b83be47b2b9a7ae374b40652d74b822387e31fa5267a37bf49c122e1a9747 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-transform-react-display-name@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-react-display-name@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 3aed142af7bd1aed1df2bdad91ed33ba1cdd5c3c67ce6eafba821ff72f129162a197ffb55f1eb1775af276abd5545934489a8257fef6c6665ddf253a4f39a939 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-react-jsx@npm:^7.0.0": + version: 7.23.4 + resolution: "@babel/plugin-transform-react-jsx@npm:7.23.4" dependencies: - eslint-visitor-keys: "npm:^3.3.0" + "@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: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - checksum: 7e559c4ce59cd3a06b1b5a517b593912e680a7f981ae7affab0d01d709e99cd5647019be8fafa38c350305bc32f1f7d42c7073edde2ab536c745e365f37b607e + "@babel/core": ^7.0.0-0 + checksum: 8851b3adc515cd91bdb06ff3a23a0f81f0069cfef79dfb3fa744da4b7a82e3555ccb6324c4fa71ecf22508db13b9ff6a0ed96675f95fc87903b9fc6afb699580 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-shorthand-properties@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-shorthand-properties@npm:7.23.3" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: c423c66fec0b6503f50561741754c84366ef9e9818442c8881fbaa90cc363fd137084b9431cdc00ed2f1fd8c8a1a5982c4a7e1f2af3769db4caf2ac7ea55d4f0 languageName: node linkType: hard -"@eslint/eslintrc@npm:^0.4.3": - version: 0.4.3 - resolution: "@eslint/eslintrc@npm:0.4.3" +"@babel/plugin-transform-spread@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-spread@npm:7.23.3" 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" + "@babel/helper-skip-transparent-expression-wrappers": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: a348e4ae47e4ceeceb760506ec7bf835ccc18a2cf70ec74ebfbe41bc172fa2412b05b7d1b86836f8aee375e41a04ff20486074778d0e2d19d668b33dc52e9dbb languageName: node linkType: hard -"@eslint/eslintrc@npm:^2.1.3": - version: 2.1.3 - resolution: "@eslint/eslintrc@npm:2.1.3" +"@babel/plugin-transform-template-literals@npm:^7.0.0": + version: 7.23.3 + resolution: "@babel/plugin-transform-template-literals@npm:7.23.3" 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-plugin-utils": "npm:^7.22.5" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 9b5f43788b9ffcb8f2b445a16b1aa40fcf23cb0446a4649445f098ec6b4cb751f243a535da623d59fefe48f4c40552f5621187a61811779076bab26863e3373d languageName: node linkType: hard -"@eslint/js@npm:8.54.0": - version: 8.54.0 - resolution: "@eslint/js@npm:8.54.0" - checksum: d61fb4a0be6af2d8cb290121c329697664a75d6255a29926d5454fb02aeb02b87112f67fdf218d10abac42f90c570ac366126751baefc5405d0e017ed0c946c5 +"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.18.3": + version: 7.23.9 + resolution: "@babel/runtime@npm:7.23.9" + dependencies: + regenerator-runtime: "npm:^0.14.0" + checksum: e71205fdd7082b2656512cc98e647d9ea7e222e4fe5c36e9e5adc026446fcc3ba7b3cdff8b0b694a0b78bb85db83e7b1e3d4c56ef90726682b74f13249cf952d languageName: node linkType: hard -"@ethereum-waffle/chai@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/chai@npm:3.4.4" +"@babel/runtime@npm:^7.20.1, @babel/runtime@npm:^7.5.5": + version: 7.23.8 + resolution: "@babel/runtime@npm:7.23.8" dependencies: - "@ethereum-waffle/provider": "npm:^3.4.4" - ethers: "npm:^5.5.2" - checksum: 69921adf1d2320e853f7d61b8ce2cf45cdba746666097dc59f7578b22374f821b245e88368c563f3fa58c32d14c981d6025342a90a3cbc005ef84afc87fee807 + regenerator-runtime: "npm:^0.14.0" + checksum: ba5e8fbb32ef04f6cab5e89c54a0497c2fde7b730595cc1af93496270314f13ff2c6a9360fdb2f0bdd4d6b376752ce3cf85642bd6b876969a6a62954934c2df8 languageName: node linkType: hard -"@ethereum-waffle/compiler@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/compiler@npm:3.4.4" +"@babel/template@npm:^7.22.15, @babel/template@npm:^7.23.9": + version: 7.23.9 + resolution: "@babel/template@npm:7.23.9" 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/code-frame": "npm:^7.23.5" + "@babel/parser": "npm:^7.23.9" + "@babel/types": "npm:^7.23.9" + checksum: 0e8b60119433787742bc08ae762bbd8d6755611c4cabbcb7627b292ec901a55af65d93d1c88572326069efb64136ef151ec91ffb74b2df7689bbab237030833a languageName: node linkType: hard -"@ethereum-waffle/ens@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/ens@npm:3.4.4" +"@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: - "@ensdomains/ens": "npm:^0.4.4" - "@ensdomains/resolver": "npm:^0.2.4" - ethers: "npm:^5.5.2" - checksum: c419924fec2dde755ec0d4a1d0bf2d1317e46370d6b5dec6cc2f85636b31e00f53dc067196d0579be8802c3d0753310f591960b60e15c16968174d4553eece21 + "@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 -"@ethereum-waffle/mock-contract@npm:^3.4.4": - version: 3.4.4 - resolution: "@ethereum-waffle/mock-contract@npm:3.4.4" +"@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/abi": "npm:^5.5.0" - ethers: "npm:^5.5.2" - checksum: cc91dee6822a772fa7c3aec555225e1dde952b39f2c6f10a2d45f9c908d71ece7e531fd56813aad9a5f9a486b85586865fee30cd30d595311137c87eb931e87d + "@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 -"@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 +"@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 -"@ethereumjs/common@npm:2.5.0": - version: 2.5.0 - resolution: "@ethereumjs/common@npm:2.5.0" +"@chainsafe/persistent-merkle-tree@npm:^0.4.2": + version: 0.4.2 + resolution: "@chainsafe/persistent-merkle-tree@npm:0.4.2" dependencies: - crc-32: "npm:^1.2.0" - ethereumjs-util: "npm:^7.1.1" - checksum: 98a11931150ccc4d204f3c5328979cac9928cbc0f73344427dc41561287f100670db8b0296ede04542b598a58a699f4709867fb652a17ab076bab0ef14185816 + "@chainsafe/as-sha256": "npm:^0.3.1" + checksum: 9533e478a1a990e8cf8710a2eeb84c6f08c7b61726a43dbe2165316256839c29a2ff17923bce5e5effec446d832de8b0a5bc896ef5db80bce059af5d1bd20d8d 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" +"@chainsafe/persistent-merkle-tree@npm:^0.5.0": + version: 0.5.0 + resolution: "@chainsafe/persistent-merkle-tree@npm:0.5.0" dependencies: - crc-32: "npm:^1.2.0" - ethereumjs-util: "npm:^7.1.5" - checksum: 065fc993e390631753e9cbc63987954338c42192d227e15a40d9a074eda9e9597916dca51970b59230c7d3b1294c5956258fe6ea29000b5555bf24fe3ff522c5 + "@chainsafe/as-sha256": "npm:^0.3.1" + checksum: 73c7a7536f49aceab61870fcc1dafef8a8be2ae0bfff2614846bb4b57a21939da75bca7bc5d1959cd312a5133be0acaf0e30fb323410c57592e9ec384758efe0 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 +"@chainsafe/ssz@npm:^0.10.0": + version: 0.10.2 + resolution: "@chainsafe/ssz@npm:0.10.2" + dependencies: + "@chainsafe/as-sha256": "npm:^0.3.1" + "@chainsafe/persistent-merkle-tree": "npm:^0.5.0" + checksum: be427eba9f9c4a542326f9f3c20eb704c1c2500c4f124ba18febf6ffd5bb7bd5755228d99326bf6c4e4d969daa4b6ff2efb743688ec36ef86f20c0c673c0e967 languageName: node linkType: hard -"@ethereumjs/tx@npm:3.3.2": - version: 3.3.2 - resolution: "@ethereumjs/tx@npm:3.3.2" +"@chainsafe/ssz@npm:^0.9.2": + version: 0.9.4 + resolution: "@chainsafe/ssz@npm:0.9.4" dependencies: - "@ethereumjs/common": "npm:^2.5.0" - ethereumjs-util: "npm:^7.1.2" - checksum: 36b38bb56e54293cc86b02cd7146c0e653235c42a765fe704e0efd9aa96c363995c201585ede798e75f974d6d123b6f775845da2c56fbce71d9d099dc03dcb16 + "@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 -"@ethereumjs/tx@npm:^3.3.2": - version: 3.5.2 - resolution: "@ethereumjs/tx@npm:3.5.2" +"@changesets/apply-release-plan@npm:^7.0.0": + version: 7.0.0 + resolution: "@changesets/apply-release-plan@npm:7.0.0" dependencies: - "@ethereumjs/common": "npm:^2.6.4" - ethereumjs-util: "npm:^7.1.5" - checksum: 768cbe0834eef15f4726b44f2a4c52b6180884d90e58108d5251668c7e89d58572de7375d5e63be9d599e79c09259e643837a2afe876126b09c47ac35386cc20 + "@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 -"@ethereumjs/util@npm:^8.1.0": - version: 8.1.0 - resolution: "@ethereumjs/util@npm:8.1.0" +"@changesets/assemble-release-plan@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/assemble-release-plan@npm:6.0.0" dependencies: - "@ethereumjs/rlp": "npm:^4.0.1" - ethereum-cryptography: "npm:^2.0.0" - micro-ftch: "npm:^0.3.1" - checksum: 4e6e0449236f66b53782bab3b387108f0ddc050835bfe1381c67a7c038fea27cb85ab38851d98b700957022f0acb6e455ca0c634249cfcce1a116bad76500160 + "@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/abi@npm:5.0.0-beta.153": - version: 5.0.0-beta.153 - resolution: "@ethersproject/abi@npm:5.0.0-beta.153" +"@changesets/changelog-git@npm:^0.2.0": + version: 0.2.0 + resolution: "@changesets/changelog-git@npm:0.2.0" 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 + "@changesets/types": "npm:^6.0.0" + checksum: d94df555656ac4ac9698d87a173b1955227ac0f1763d59b9b4d4f149ab3f879ca67603e48407b1dfdadaef4e7882ae7bbc7b7be160a45a55f05442004bdc61bd languageName: node linkType: hard -"@ethersproject/abi@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/abi@npm:5.6.0" +"@changesets/cli@npm:^2.27.1": + version: 2.27.1 + resolution: "@changesets/cli@npm:2.27.1" 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/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/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" +"@changesets/config@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/config@npm:3.0.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/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 + "@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/abstract-provider@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/abstract-provider@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" - "@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 + extendable-error: "npm:^0.1.5" + checksum: f2757c752ab04e9733b0dfd7903f1caf873f9e603794c4d9ea2294af4f937c73d07273c24be864ad0c30b6a98424360d5b96a6eab14f97f3cf2cbfd3763b95c1 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" +"@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" - "@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 + "@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/abstract-signer@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/abstract-signer@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/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/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/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" - 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 +"@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/address@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/address@npm:5.6.0" +"@changesets/git@npm:^3.0.0": + version: 3.0.0 + resolution: "@changesets/git@npm:3.0.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 + "@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/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" +"@changesets/logger@npm:^0.1.0": + version: 0.1.0 + resolution: "@changesets/logger@npm:0.1.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 + chalk: "npm:^2.1.0" + checksum: b40365a4e62be4bf7a75c5900e8f95b1abd8fb9ff9f2cf71a7b567532377ddd5490b0ee1d566189a91e8c8250c9e875d333cfb3e44a34c230a11fd61337f923e languageName: node linkType: hard -"@ethersproject/base64@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/base64@npm:5.6.0" +"@changesets/parse@npm:^0.4.0": + version: 0.4.0 + resolution: "@changesets/parse@npm:0.4.0" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - checksum: 5aa21dfae72a59495823ad89251a56813dd63160d593aa126c2dfc4bd4d650318d81e4000eff6cd1eb8cfce2494300a1bf9a96e2688e2fba642e8bc5bc7a363e + "@changesets/types": "npm:^6.0.0" + js-yaml: "npm:^3.13.1" + checksum: 8e76f8540aceb2263eb76c97f027c1990fc069bf275321ad0aabf843cb51bc6711b13118eda35c701a30a36d26f48e75f7afc14e9a5c863f8a98091021fd5d61 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" +"@changesets/pre@npm:^2.0.0": + version: 2.0.0 + resolution: "@changesets/pre@npm:2.0.0" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - checksum: 4f748cd82af60ff1866db699fbf2bf057feff774ea0a30d1f03ea26426f53293ea10cc8265cda1695301da61093bedb8cc0d38887f43ed9dad96b78f19d7337e + "@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/basex@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/basex@npm:5.6.0" +"@changesets/read@npm:^0.6.0": + version: 0.6.0 + resolution: "@changesets/read@npm:0.6.0" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/properties": "npm:^5.6.0" - checksum: db108a14a7a34e538d993c8fcd18444226f9c65af80672670c784ced56b8b8e07348176394525a2675971fb30406a035dc9a3038cd478d05099712b48ba6d87f + "@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/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 +"@changesets/types@npm:^4.0.1": + version: 4.1.0 + resolution: "@changesets/types@npm:4.1.0" + checksum: a372ad21f6a1e0d4ce6c19573c1ca269eef1ad53c26751ad9515a24f003e7c49dcd859dbb1fedb6badaf7be956c1559e8798304039e0ec0da2d9a68583f13464 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/types@npm:^6.0.0": + version: 6.0.0 + resolution: "@changesets/types@npm:6.0.0" + checksum: e755f208792547e3b9ece15ce4da22466267da810c6fd87d927a1b8cec4d7fb7f0eea0d1a7585747676238e3e4ba1ffdabe016ccb05cfa537b4e4b03ec399f41 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/write@npm:^0.3.0": + version: 0.3.0 + resolution: "@changesets/write@npm:0.3.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/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/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 +"@colors/colors@npm:1.5.0": + version: 1.5.0 + resolution: "@colors/colors@npm:1.5.0" + checksum: eb42729851adca56d19a08e48d5a1e95efd2a32c55ae0323de8119052be0510d4b7a1611f2abcbf28c044a6c11e6b7d38f99fccdad7429300c37a8ea5fb95b44 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" - dependencies: - "@ethersproject/logger": "npm:^5.7.0" - checksum: 07dd1f0341b3de584ef26c8696674ff2bb032f4e99073856fc9cd7b4c54d1d846cabe149e864be267934658c3ce799e5ea26babe01f83af0e1f06c51e5ac791f +"@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 -"@ethersproject/constants@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/constants@npm:5.6.0" +"@commitlint/cli@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/cli@npm:18.4.3" dependencies: - "@ethersproject/bignumber": "npm:^5.6.0" - checksum: 61c8b0ceab8a3bdf10b15bd32c16343ea3149ddafaedb6698fb7fcf850e29061323cb3fcf93a00c79f33ba481f3e5e2547e1dc63ace9fe46fcdb48bf69e8d31b + "@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 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" +"@commitlint/config-conventional@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/config-conventional@npm:18.4.3" dependencies: - "@ethersproject/bignumber": "npm:^5.7.0" - checksum: 6df63ab753e152726b84595250ea722165a5744c046e317df40a6401f38556385a37c84dadf5b11ca651c4fb60f967046125369c57ac84829f6b30e69a096273 + conventional-changelog-conventionalcommits: "npm:^7.0.2" + checksum: 13977d8c9cbac31c172ead77c36da5fd88c980438a9811e2b5447f994442200daf8d2d37c5ffef9f5b6afef100513a2ac1e3ec94ba667d7a62fce117e57a16b1 languageName: node linkType: hard -"@ethersproject/contracts@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/contracts@npm:5.6.0" +"@commitlint/config-validator@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/config-validator@npm:18.4.3" 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 + "@commitlint/types": "npm:^18.4.3" + ajv: "npm:^8.11.0" + checksum: 8e6f3130a2e9c17c08276fc81b16e70320af27718bfdfc954e5a591538a23f9510bbbf61f60499d5e09488f112df9400730f065c7309006a9e9da7bd1d371385 languageName: node linkType: hard -"@ethersproject/contracts@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/contracts@npm:5.7.0" +"@commitlint/ensure@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/ensure@npm:18.4.3" 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 + "@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 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" - dependencies: - "@ethersproject/web": "npm:^5.7.0" - ethers: "npm:^5.7.0" - scrypt-js: "npm:3.0.1" - checksum: 0546f8737ca062ce7d4a890d9cb354fde34b10b042b1d6b26e7206810c39d0fdb7ac20e60686a89f3f41faf33cc4c4c7366f49700a2d0978f0457e79759a79a4 +"@commitlint/execute-rule@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/execute-rule@npm:18.4.3" + checksum: 6a0514733c3fab7279b4831df58f518b98c589d05eace2d9b5f1f64d05f9f1493af51f3b6004df4f90e794b98798ee07cf4c5fbe9e97f37d5437a50cd56bf52f languageName: node linkType: hard -"@ethersproject/hash@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/hash@npm:5.6.0" +"@commitlint/format@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/format@npm:18.4.3" 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 + "@commitlint/types": "npm:^18.4.3" + chalk: "npm:^4.1.0" + checksum: c2ed05e17f2038af79b39ec0d5bd74d42c2ddd9da4eee22ca372414625084b34f69b24e9372c00a3eb061364a258e1a6eb43f9def38ef6e7995606459d900f15 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" +"@commitlint/is-ignored@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/is-ignored@npm:18.4.3" 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 + "@commitlint/types": "npm:^18.4.3" + semver: "npm:7.5.4" + checksum: 9b2456e0b31656eb1c2828d6a4c0ec12815bfb88e734bc673315a08a6ef5b19e96ecd0cc925d88b797bafe4c09a3aca7d5841c02f8e5de4cc88473bbfba1a275 languageName: node linkType: hard -"@ethersproject/hdnode@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/hdnode@npm:5.6.0" +"@commitlint/lint@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/lint@npm:18.4.3" 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 + "@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 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" +"@commitlint/load@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/load@npm:18.4.3" 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 + "@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 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 +"@commitlint/message@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/message@npm:18.4.3" + checksum: 24b373d5c99230351a31294e974ee338cbac45094c66a6ba9ce00357783f7ebb250fc169fcdd815c8d510951757119fbd1329e7ab9e3097d3e732768d3d93787 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" +"@commitlint/parse@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/parse@npm:18.4.3" 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 + "@commitlint/types": "npm:^18.4.3" + conventional-changelog-angular: "npm:^7.0.0" + conventional-commits-parser: "npm:^5.0.0" + checksum: ce25e90a9f0920ce8bd1bf9a56ca250394b60d5c63d5fb9e41e047c64f8278ecfffc121a872662dead80dbcc4c3afaf3b80f93e89e8f8ca1d5f05ff0f145813c languageName: node linkType: hard -"@ethersproject/keccak256@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/keccak256@npm:5.6.0" +"@commitlint/read@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/read@npm:18.4.3" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - js-sha3: "npm:0.8.0" - checksum: 3f99e3bd7b1125bad4c1ac10c133c2e09b93d7675bc9a54e4b0f608520ebf20df36f6d83dd6804f2cbea3b51ffd800cc9532f7239c5e0803aa58d62d7f0d0d94 + "@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 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/resolve-extends@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/resolve-extends@npm:18.4.3" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - js-sha3: "npm:0.8.0" - checksum: 3b1a91706ff11f5ab5496840b9c36cedca27db443186d28b94847149fd16baecdc13f6fc5efb8359506392f2aba559d07e7f9c1e17a63f9d5de9f8053cfcb033 + "@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 languageName: node linkType: hard -"@ethersproject/logger@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/logger@npm:5.6.0" - checksum: f4c2610cf25d833cc1bc0a4ce99227c30508f15c8acb423e8a15f12ac25e37f9f86779485e6f79a887b24df831bdbee949249eb5feb75c6b45ca761161739516 +"@commitlint/rules@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/rules@npm:18.4.3" + 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 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/to-lines@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/to-lines@npm:18.4.3" + checksum: a163a647ebcdc9fb8a84f3406f92fde78b90cc73146c367367806d52022c6b6219b78f5b0afea0faab357f95b9e311822bc9309a0148fd31f30bdb77bfcfd84a languageName: node linkType: hard -"@ethersproject/networks@npm:5.6.1": - version: 5.6.1 - resolution: "@ethersproject/networks@npm:5.6.1" +"@commitlint/top-level@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/top-level@npm:18.4.3" dependencies: - "@ethersproject/logger": "npm:^5.6.0" - checksum: 3628b2a302dedbcb0c8c36f3e42faa688fdb46c7afe28ce95d02d2a5306a865b2f6c2e72ce6f701c3d15291d09e626d22910c10f39ea9016997ec1977d16a310 + find-up: "npm:^5.0.0" + checksum: 69a75878a18ba812e12be899c3b032c1067d093261e7c622f18a3110bc83483d75fa9c2a589086590a9896d389b407cc58d324803821c314bf952912f57b0095 languageName: node linkType: hard -"@ethersproject/networks@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/networks@npm:5.7.0" +"@commitlint/types@npm:^18.4.3": + version: 18.4.3 + resolution: "@commitlint/types@npm:18.4.3" dependencies: - "@ethersproject/logger": "npm:^5.7.0" - checksum: ac9f921a196bc8f7816c1ba43262bb22701f00ab599f4af8bd7275a7728b748ff428dd3445d375f7b2abdfe29bf85eff77cf132d25df8c78ff504c6b86c56e6e + chalk: "npm:^4.1.0" + checksum: 07cbc4b5eb813052401d9e332c0dadca7864cd22eddd06edb6afd1da212243d505c4429ce100012c4086ea99d0f4a4086382fc88e3e662c6577e69d638c3903e 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" +"@cspotcode/source-map-support@npm:^0.8.0": + version: 0.8.1 + resolution: "@cspotcode/source-map-support@npm:0.8.1" dependencies: - "@ethersproject/logger": "npm:^5.7.0" - checksum: 9efcdce27f150459e85d74af3f72d5c32898823a99f5410e26bf26cca2d21fb14e403377314a93aea248e57fb2964e19cee2c3f7bfc586ceba4c803a8f1b75c0 + "@jridgewell/trace-mapping": "npm:0.3.9" + checksum: 05c5368c13b662ee4c122c7bfbe5dc0b613416672a829f3e78bc49a357a197e0218d6e74e7c66cfcd04e15a179acab080bd3c69658c9fbefd0e1ccd950a07fc6 languageName: node linkType: hard -"@ethersproject/pbkdf2@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/pbkdf2@npm:5.6.0" +"@dabh/diagnostics@npm:^2.0.2": + version: 2.0.3 + resolution: "@dabh/diagnostics@npm:2.0.3" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/sha2": "npm:^5.6.0" - checksum: 5dbf03cb20dcd794db08dec21fc2a56feed7d13cf78d2358933ff936d6499b7d3c0169d0fde33cc0bfee31186df0db1dc732fd881499f3274964115be8140dfd + colorspace: "npm:1.1.x" + enabled: "npm:2.0.x" + kuler: "npm:^2.0.0" + checksum: a5133df8492802465ed01f2f0a5784585241a1030c362d54a602ed1839816d6c93d71dde05cf2ddb4fd0796238c19774406bd62fa2564b637907b495f52425fe 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" +"@defi-wonderland/smock@npm:^2.0.7": + version: 2.3.5 + resolution: "@defi-wonderland/smock@npm:2.3.5" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/sha2": "npm:^5.7.0" - checksum: e5a29cf28b4f4ca1def94d37cfb6a9c05c896106ed64881707813de01c1e7ded613f1e95febcccda4de96aae929068831d72b9d06beef1377b5a1a13a0eb3ff5 + "@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/properties@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/properties@npm:5.6.0" +"@ensdomains/ens@npm:^0.4.4": + version: 0.4.5 + resolution: "@ensdomains/ens@npm:0.4.5" dependencies: - "@ethersproject/logger": "npm:^5.6.0" - checksum: a137e1002d1af1e37b81279df370081c5c0fab7492fedc9798a52c10c79c6c792fef30742bc8920570cf73bfff06d6f88e89b1ef68ebbb0360d1d8f1efa8fba9 + 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/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 +"@ensdomains/resolver@npm:^0.2.4": + version: 0.2.4 + resolution: "@ensdomains/resolver@npm:0.2.4" + checksum: 8bd21f82c3f122f56d7198cf671c08204cca2cb531fd5074fd558d625afa8a15828e92738bf80b9961575a92e4fe627208edd3f87a04c6a0fa47531c91ef0639 languageName: node linkType: hard -"@ethersproject/providers@npm:5.6.2": - version: 5.6.2 - resolution: "@ethersproject/providers@npm:5.6.2" +"@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/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 + "@envelop/types": "npm:3.0.2" + tslib: "npm:^2.5.0" + checksum: 8196e997f351b7d1630fc6cfb6aa0fb4257dd1769cde12da227418508f1be433ed94271b433c47b5ccd5079728b93cdb7326738afda76d49c791f3ed736d7fc5 languageName: node linkType: hard -"@ethersproject/providers@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/providers@npm:5.7.0" +"@envelop/extended-validation@npm:^2.0.6": + version: 2.0.6 + resolution: "@envelop/extended-validation@npm:2.0.6" 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 + "@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/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" +"@envelop/types@npm:3.0.2": + version: 3.0.2 + resolution: "@envelop/types@npm:3.0.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 + tslib: "npm:^2.5.0" + checksum: 1e71237bdb0d65256136760227402306e9d5aec1306f9e437085de2a1a0d8ea007be9302e9e397f96fd455f65da33cb3fe5822757af680ade9cecf218ce42a7c languageName: node linkType: hard -"@ethersproject/random@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/random@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/logger": "npm:^5.6.0" - checksum: 85f56fcd572f158a9cbc7ca27d4f139bdb6073b1a5859940cbb6d11ffdb5d9a8b7adf812d726e590947ec2eb99ed7b86c06fcef081e0edb8ed7b7753ee84a02c + 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/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" +"@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/logger": "npm:^5.7.0" - checksum: 23e572fc55372653c22062f6a153a68c2e2d3200db734cd0d39621fbfd0ca999585bed2d5682e3ac65d87a2893048375682e49d1473d9965631ff56d2808580b + 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/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 +"@eslint-community/regexpp@npm:^4.4.0, @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/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" +"@eslint/eslintrc@npm:^0.4.3": + version: 0.4.3 + resolution: "@eslint/eslintrc@npm:0.4.3" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - checksum: bc863d21dcf7adf6a99ae75c41c4a3fb99698cfdcfc6d5d82021530f3d3551c6305bc7b6f0475ad6de6f69e91802b7e872bee48c0596d98969aefcf121c2a044 + 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 languageName: node linkType: hard -"@ethersproject/sha2@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/sha2@npm:5.6.0" +"@eslint/eslintrc@npm:^2.1.3": + version: 2.1.3 + resolution: "@eslint/eslintrc@npm:2.1.3" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - hash.js: "npm:1.1.7" - checksum: a56818968c89213146f57cadfc20949157dbb6643fb6d40f4a6cd7fb4b0433d5e679cc5b7b9e2efa5a7c20ae6e7f634ac8f7f560431f158aa94b05d621c3b1f8 + 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 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" +"@eslint/eslintrc@npm:^2.1.4": + version: 2.1.4 + resolution: "@eslint/eslintrc@npm:2.1.4" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - hash.js: "npm:1.1.7" - checksum: 0e7f9ce6b1640817b921b9c6dd9dab8d5bf5a0ce7634d6a7d129b7366a576c2f90dcf4bcb15a0aa9310dde67028f3a44e4fcc2f26b565abcd2a0f465116ff3b1 + 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/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 +"@eslint/js@npm:8.54.0": + version: 8.54.0 + resolution: "@eslint/js@npm:8.54.0" + checksum: d61fb4a0be6af2d8cb290121c329697664a75d6255a29926d5454fb02aeb02b87112f67fdf218d10abac42f90c570ac366126751baefc5405d0e017ed0c946c5 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 +"@eslint/js@npm:8.56.0": + version: 8.56.0 + resolution: "@eslint/js@npm:8.56.0" + checksum: 60b3a1cf240e2479cec9742424224465dc50e46d781da1b7f5ef240501b2d1202c225bd456207faac4b34a64f4765833345bc4ddffd00395e1db40fa8c426f5a languageName: node linkType: hard -"@ethersproject/solidity@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/solidity@npm:5.6.0" +"@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/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 + "@ethereum-waffle/provider": "npm:^3.4.4" + ethers: "npm:^5.5.2" + checksum: 69921adf1d2320e853f7d61b8ce2cf45cdba746666097dc59f7578b22374f821b245e88368c563f3fa58c32d14c981d6025342a90a3cbc005ef84afc87fee807 languageName: node linkType: hard -"@ethersproject/solidity@npm:5.7.0": - version: 5.7.0 - resolution: "@ethersproject/solidity@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/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 + "@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/strings@npm:5.6.0": - version: 5.6.0 - resolution: "@ethersproject/strings@npm:5.6.0" +"@ethereum-waffle/ens@npm:^3.4.4": + version: 3.4.4 + resolution: "@ethereum-waffle/ens@npm:3.4.4" dependencies: - "@ethersproject/bytes": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" - "@ethersproject/logger": "npm:^5.6.0" - checksum: bd0fea07ac99365b4da10654419415c88ad319d8229a9b0fbd26632ed9549fb033e6cd491c5504d437718173254247628d223ebcab6d29e3ab9046b66563fdba + "@ensdomains/ens": "npm:^0.4.4" + "@ensdomains/resolver": "npm:^0.2.4" + ethers: "npm:^5.5.2" + checksum: c419924fec2dde755ec0d4a1d0bf2d1317e46370d6b5dec6cc2f85636b31e00f53dc067196d0579be8802c3d0753310f591960b60e15c16968174d4553eece21 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" +"@ethereum-waffle/mock-contract@npm:^3.4.4": + version: 3.4.4 + resolution: "@ethereum-waffle/mock-contract@npm:3.4.4" dependencies: - "@ethersproject/bytes": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" - "@ethersproject/logger": "npm:^5.7.0" - checksum: 570d87040ccc7d94de9861f76fc2fba6c0b84c5d6104a99a5c60b8a2401df2e4f24bf9c30afa536163b10a564a109a96f02e6290b80e8f0c610426f56ad704d1 + "@ethersproject/abi": "npm:^5.5.0" + ethers: "npm:^5.5.2" + checksum: cc91dee6822a772fa7c3aec555225e1dde952b39f2c6f10a2d45f9c908d71ece7e531fd56813aad9a5f9a486b85586865fee30cd30d595311137c87eb931e87d languageName: node linkType: hard -"@ethersproject/transactions@npm:5.6.0": +"@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/transactions@npm:5.6.0" + resolution: "@ethersproject/abi@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/hash": "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 + "@ethersproject/strings": "npm:^5.6.0" + checksum: 17bfdeade4fed887b64708b409c665a034a94fc0d409b6f95498f0f752dd27306e71f1de55ce231f3fc0034f4579943e572ef742673ec6e5d69c136cbe70d942 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": +"@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/transactions@npm:5.7.0" + resolution: "@ethersproject/abi@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/hash": "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 + "@ethersproject/strings": "npm:^5.7.0" + checksum: 7de51bf52ff03df2526546dacea6e74f15d4c5ef762d931552082b9600dcefd8e333599f02d7906ba89f7b7f48c45ab72cee76f397212b4f17fa9d9ff5615916 languageName: node linkType: hard -"@ethersproject/units@npm:5.6.0": +"@ethersproject/abstract-provider@npm:5.6.0": version: 5.6.0 - resolution: "@ethersproject/units@npm:5.6.0" + resolution: "@ethersproject/abstract-provider@npm:5.6.0" dependencies: "@ethersproject/bignumber": "npm:^5.6.0" - "@ethersproject/constants": "npm:^5.6.0" + "@ethersproject/bytes": "npm:^5.6.0" "@ethersproject/logger": "npm:^5.6.0" - checksum: cb92acc910e00030009de917d9a7cea72def0536aceaaa9132d3d9fcedf4b39c7645ffc3950e747763a01048bb16ccd34cb0f0d6916d4d6a209ea809180a76be + "@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 languageName: node linkType: hard -"@ethersproject/units@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/units@npm:5.7.0" + resolution: "@ethersproject/abstract-provider@npm:5.7.0" dependencies: "@ethersproject/bignumber": "npm:^5.7.0" - "@ethersproject/constants": "npm:^5.7.0" + "@ethersproject/bytes": "npm:^5.7.0" "@ethersproject/logger": "npm:^5.7.0" - checksum: 4da2fdefe2a506cc9f8b408b2c8638ab35b843ec413d52713143f08501a55ff67a808897f9a91874774fb526423a0821090ba294f93e8bf4933a57af9677ac5e + "@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 languageName: node linkType: hard -"@ethersproject/wallet@npm:5.6.0": +"@ethersproject/abstract-signer@npm:5.6.0": version: 5.6.0 - resolution: "@ethersproject/wallet@npm:5.6.0" + resolution: "@ethersproject/abstract-signer@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 + checksum: 8c84e7545fda6b7ebf2115700f5bdd6d41ba89a1547bc7fab51ce3ada4802d6ea84d5c87700c212d999ee6f8f374e8e123b1f67b08ff99dd77bd1defb633e042 languageName: node linkType: hard -"@ethersproject/wallet@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/wallet@npm:5.7.0" + resolution: "@ethersproject/abstract-signer@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 + checksum: e174966b3be17269a5974a3ae5eef6d15ac62ee8c300ceace26767f218f6bbf3de66f29d9a9c9ca300fa8551aab4c92e28d2cc772f5475fdeaa78d9b5be0e745 languageName: node linkType: hard -"@ethersproject/web@npm:5.6.0": +"@ethersproject/address@npm:5.6.0": version: 5.6.0 - resolution: "@ethersproject/web@npm:5.6.0" + resolution: "@ethersproject/address@npm:5.6.0" dependencies: - "@ethersproject/base64": "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: 10fc728c022e664675a4e3d367c56bec465a1f7e8fd987c8eccfae57600276fd4a4fd2a86c2bf303c37939dd4480f9ccdf7249a4789297bc3bae5daee19e33c2 + "@ethersproject/rlp": "npm:^5.6.0" + checksum: dada2e1d800085ef97d380f84d7a929cfccc78856ead06c122045c2bfb896cd5affb47f01fb31af70cad56172135afc93679051267847d5896f3efcb2cbba216 languageName: node linkType: hard -"@ethersproject/web@npm:5.7.0": +"@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/web@npm:5.7.0" + resolution: "@ethersproject/address@npm:5.7.0" dependencies: - "@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: c5cc371e7c5d58a8f8b8aaf98df3a1dff451534d49c266a847a9f2956e009fedf77281a5b65ed5f1ea3fb071bbf3f58ec07aa9159082359db063d11b23b886c5 + "@ethersproject/rlp": "npm:^5.7.0" + checksum: db5da50abeaae8f6cf17678323e8d01cad697f9a184b0593c62b71b0faa8d7e5c2ba14da78a998d691773ed6a8eb06701f65757218e0eaaeb134e5c5f3e5a908 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" +"@ethersproject/base64@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/base64@npm:5.6.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: c82d6745c7f133980e8dab203955260e07da22fa544ccafdd0f21c79fae127bd6ef30957319e37b1cc80cddeb04d6bfb60f291bb14a97c9093d81ce50672f453 + "@ethersproject/bytes": "npm:^5.6.0" + checksum: 5aa21dfae72a59495823ad89251a56813dd63160d593aa126c2dfc4bd4d650318d81e4000eff6cd1eb8cfce2494300a1bf9a96e2688e2fba642e8bc5bc7a363e languageName: node linkType: hard -"@ethersproject/wordlists@npm:5.6.0": +"@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/wordlists@npm:5.6.0" + resolution: "@ethersproject/basex@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 + checksum: db108a14a7a34e538d993c8fcd18444226f9c65af80672670c784ced56b8b8e07348176394525a2675971fb30406a035dc9a3038cd478d05099712b48ba6d87f languageName: node linkType: hard -"@ethersproject/wordlists@npm:5.7.0, @ethersproject/wordlists@npm:^5.6.0, @ethersproject/wordlists@npm:^5.7.0": +"@ethersproject/basex@npm:5.7.0, @ethersproject/basex@npm:^5.6.0, @ethersproject/basex@npm:^5.7.0": version: 5.7.0 - resolution: "@ethersproject/wordlists@npm:5.7.0" + resolution: "@ethersproject/basex@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 + checksum: 02304de77477506ad798eb5c68077efd2531624380d770ef4a823e631a288fb680107a0f9dc4a6339b2a0b0f5b06ee77f53429afdad8f950cde0f3e40d30167d languageName: node linkType: hard -"@fastify/busboy@npm:^2.0.0": - version: 2.1.0 - resolution: "@fastify/busboy@npm:2.1.0" - checksum: 7bb641080aac7cf01d88749ad331af10ba9ec3713ec07cabbe833908c75df21bd56249bb6173bdec07f5a41896b21e3689316f86684c06635da45f91ff4565a2 +"@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 -"@graphprotocol/common-ts@npm:^1.8.3": - version: 1.8.7 - resolution: "@graphprotocol/common-ts@npm:1.8.7" +"@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: - "@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 + "@ethersproject/bytes": "npm:^5.7.0" + "@ethersproject/logger": "npm:^5.7.0" + bn.js: "npm:^5.2.1" + checksum: 14263cdc91a7884b141d9300f018f76f69839c47e95718ef7161b11d2c7563163096fee69724c5fa8ef6f536d3e60f1c605819edbc478383a2b98abcde3d37b2 languageName: node linkType: hard -"@graphprotocol/common-ts@npm:^2.0.7": - version: 2.0.9 - resolution: "@graphprotocol/common-ts@npm:2.0.9" +"@ethersproject/bytes@npm:5.6.1": + version: 5.6.1 + resolution: "@ethersproject/bytes@npm:5.6.1" 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 + "@ethersproject/logger": "npm:^5.6.0" + checksum: 6bc6c8d7eebfe13b2976851920bf11e6b0dcc2ee91a8e013ca6ab9b55a4de7ccf9b3c8f4cdc777547c5ddc795a8ada0bf79ca91482e88d01e3957c901c0fef55 languageName: node linkType: hard -"@graphprotocol/contracts-monorepo@workspace:.": - version: 0.0.0-use.local - resolution: "@graphprotocol/contracts-monorepo@workspace:." +"@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: - "@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 + "@ethersproject/logger": "npm:^5.7.0" + checksum: 07dd1f0341b3de584ef26c8696674ff2bb032f4e99073856fc9cd7b4c54d1d846cabe149e864be267934658c3ce799e5ea26babe01f83af0e1f06c51e5ac791f + languageName: node + linkType: hard -"@graphprotocol/contracts@npm:2.1.0": - version: 2.1.0 - resolution: "@graphprotocol/contracts@npm:2.1.0" +"@ethersproject/constants@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/constants@npm:5.6.0" dependencies: - console-table-printer: "npm:^2.11.1" - ethers: "npm:^5.6.0" - checksum: 948c7f667b9e7efb83b06e06fd7218d044b8a1c8fed37a555f784d9ef2ef6c840306d64163dd1d82657d61d2edb563eff35af9b96bb2ef9e76ea59a6b46b6282 + "@ethersproject/bignumber": "npm:^5.6.0" + checksum: 61c8b0ceab8a3bdf10b15bd32c16343ea3149ddafaedb6698fb7fcf850e29061323cb3fcf93a00c79f33ba481f3e5e2547e1dc63ace9fe46fcdb48bf69e8d31b languageName: node linkType: hard -"@graphprotocol/contracts@npm:5.3.3": - version: 5.3.3 - resolution: "@graphprotocol/contracts@npm:5.3.3" +"@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: - console-table-printer: "npm:^2.11.1" - ethers: "npm:^5.6.0" - checksum: 00d5fd682e829da8747eaebc65645b660e7551234fbd8a05f72b7b75ce6537dbfe51e410d84eeaa4dfe7dc87c16c276b50c30fcb6d528c83fa42698acc306af3 + "@ethersproject/bignumber": "npm:^5.7.0" + checksum: 6df63ab753e152726b84595250ea722165a5744c046e317df40a6401f38556385a37c84dadf5b11ca651c4fb60f967046125369c57ac84829f6b30e69a096273 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" +"@ethersproject/contracts@npm:5.6.0": + version: 5.6.0 + resolution: "@ethersproject/contracts@npm:5.6.0" 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.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" - "@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 + "@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.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.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" + "@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 + +"@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.12" + "@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" + "@typescript-eslint/eslint-plugin": "npm:^5.20.0" + "@typescript-eslint/parser": "npm:^5.20.0" + chai: "npm:^4.2.0" + coingecko-api: "npm:^1.0.10" + consola: "npm:^2.15.0" + dotenv: "npm:^16.0.0" + eslint: "npm:^8.13.0" + eslint-config-prettier: "npm:^8.5.0" + eslint-config-standard: "npm:^16.0.3" + eslint-plugin-import: "npm:^2.22.0" + eslint-plugin-mocha-no-only: "npm:^1.1.1" + eslint-plugin-node: "npm:^11.1.0" + eslint-plugin-prettier: "npm:^4.0.0" + eslint-plugin-promise: "npm:^6.0.0" + eslint-plugin-standard: "npm:5.0.0" + 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:^2.1.1" + prettier-plugin-solidity: "npm:^1.0.0-alpha.56" + solhint: "npm:^3.3.7" + solhint-plugin-prettier: "npm:^0.0.5" + 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 + +"@graphql-tools/executor-graphql-ws@npm:^0.0.14": + version: 0.0.14 + resolution: "@graphql-tools/executor-graphql-ws@npm:0.0.14" + dependencies: + "@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 + +"@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: + "@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 + +"@graphql-tools/executor@npm:^0.0.18": + version: 0.0.18 + resolution: "@graphql-tools/executor@npm:0.0.18" + dependencies: + "@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 + +"@graphql-tools/executor@npm:^0.0.20": + version: 0.0.20 + resolution: "@graphql-tools/executor@npm:0.0.20" + dependencies: + "@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 + +"@graphql-tools/graphql-file-loader@npm:^7.5.17": + version: 7.5.17 + resolution: "@graphql-tools/graphql-file-loader@npm:7.5.17" + dependencies: + "@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 + +"@graphql-tools/graphql-tag-pluck@npm:7.5.2": + version: 7.5.2 + resolution: "@graphql-tools/graphql-tag-pluck@npm:7.5.2" + dependencies: + "@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 + +"@graphql-tools/import@npm:6.7.18": + version: 6.7.18 + resolution: "@graphql-tools/import@npm:6.7.18" + dependencies: + "@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/pino-sentry-simple@npm:0.7.1": - version: 0.7.1 - resolution: "@graphprotocol/pino-sentry-simple@npm:0.7.1" +"@graphql-tools/load@npm:^7.8.14": + version: 7.8.14 + resolution: "@graphql-tools/load@npm:7.8.14" 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/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 -"@graphprotocol/sdk@workspace:^0.5.0, @graphprotocol/sdk@workspace:packages/sdk": - version: 0.0.0-use.local - resolution: "@graphprotocol/sdk@workspace:packages/sdk" +"@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: - "@arbitrum/sdk": "npm:^3.1.12" - "@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 + "@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-typed-document-node/core@npm:^3.1.1": +"@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.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: @@ -1969,6 +3694,37 @@ __metadata: languageName: node linkType: hard +"@graphql-yoga/logger@npm:^0.0.1": + version: 0.0.1 + resolution: "@graphql-yoga/logger@npm:0.0.1" + dependencies: + tslib: "npm:^2.3.1" + checksum: 9d786cf0de21230310874d29987695b510749f0ff3a92ded3565e837e9d141588ac8fc8669a3ab235ec0dffe4ffe920e7546004858c7d06af8ee85bdd4d09c05 + languageName: node + linkType: hard + +"@graphql-yoga/subscription@npm:^3.1.0": + version: 3.1.0 + resolution: "@graphql-yoga/subscription@npm:3.1.0" + dependencies: + "@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": version: 0.11.13 resolution: "@humanwhocodes/config-array@npm:0.11.13" @@ -2026,6 +3782,17 @@ __metadata: languageName: node linkType: hard +"@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": version: 3.1.1 resolution: "@jridgewell/resolve-uri@npm:3.1.1" @@ -2033,7 +3800,21 @@ __metadata: languageName: node linkType: hard -"@jridgewell/sourcemap-codec@npm:^1.4.10": +"@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.14": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" checksum: 0c6b5ae663087558039052a626d2d7ed5208da36cfd707dcc5cea4a07cfc918248403dcb5989a8f7afaf245ce0573b7cc6fd94c4a30453bd10e44d9363940ba5 @@ -2050,6 +3831,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" @@ -2222,6 +4013,20 @@ __metadata: languageName: node linkType: hard +"@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.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" + checksum: 9f8cb09f5910275188b1ad48611856c14131ad28022b958cc648f8e095fadd41002454a3396c612c2977691e59a8baad4f6adf07aab3f9c4b20b5f24c71dd7a0 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2": version: 6.2.2 resolution: "@nomicfoundation/ethereumjs-blockchain@npm:6.2.2" @@ -2284,6 +4089,24 @@ __metadata: languageName: node linkType: hard +"@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" + lru-cache: "npm:^10.0.0" + checksum: 47f73fea07880edb68b2614981226d9315a1a3dc673d0e09d68f0bc9ebd93cbfe6ccceb3cb56f777dc9b9386cff39878349fd7474d460a38478e7175b47788f9 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-common@npm:3.1.2": version: 3.1.2 resolution: "@nomicfoundation/ethereumjs-common@npm:3.1.2" @@ -2314,6 +4137,15 @@ __metadata: languageName: node linkType: hard +"@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.4" + checksum: efaaebe41c2a3fe8b50bf12d9d134dc7611907f6eb2118f7822eaa375c54bc71bf6f6a3b2e22c754867f2cd28d619afd892b1eaa26cf1c886e0f793bda481070 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-ethash@npm:2.0.5": version: 2.0.5 resolution: "@nomicfoundation/ethereumjs-ethash@npm:2.0.5" @@ -2356,6 +4188,19 @@ __metadata: languageName: node linkType: hard +"@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.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: c4cb846b656720910fe6d4a741ad0be93833c701456da983fa3a1795dda6faaa0ab4fb3130446e648db94b68358e1e4e30024d372fb40d3f65a40650af1a83bc + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-evm@npm:1.3.2, @nomicfoundation/ethereumjs-evm@npm:^1.0.0-rc.3": version: 1.3.2 resolution: "@nomicfoundation/ethereumjs-evm@npm:1.3.2" @@ -2404,6 +4249,22 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-evm@npm:2.0.4": + version: 2.0.4 + resolution: "@nomicfoundation/ethereumjs-evm@npm:2.0.4" + dependencies: + "@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" + rustbn-wasm: "npm:^0.2.0" + checksum: f21f4d0f1a74c903934d1c6c3abcd1342c9a812c71f142999c9f3f823119761cfdb4e89e829195fa446adb772b7f4b23ee9d55ed31bd92d5d03df438c3c29202 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-rlp@npm:4.0.3": version: 4.0.3 resolution: "@nomicfoundation/ethereumjs-rlp@npm:4.0.3" @@ -2431,6 +4292,15 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-rlp@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-rlp@npm:5.0.4" + bin: + rlp: bin/rlp.cjs + checksum: 58e276c190f5f33e12ff4a2c7fe4c3c71cb139029eddd9b46488e23e168c422bc0b55368c0b7805ca8b09e9ea6b8298cd74c63f5c2ed4b6fb447635ed7a317f7 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5": version: 1.0.5 resolution: "@nomicfoundation/ethereumjs-statemanager@npm:1.0.5" @@ -2474,6 +4344,27 @@ __metadata: languageName: node linkType: hard +"@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.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" + js-sdsl: "npm:^4.1.4" + 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 + "@nomicfoundation/ethereumjs-trie@npm:5.0.5": version: 5.0.5 resolution: "@nomicfoundation/ethereumjs-trie@npm:5.0.5" @@ -2512,6 +4403,20 @@ __metadata: languageName: node linkType: hard +"@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.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: b475d858f98037431c54c7177d0ce95133a81f1ee98a0b042136d65c88b7b5b3d86ba981cf78292776781d43d60daed44edf508ff4d416355bd00517e9142c9f + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-tx@npm:4.1.2": version: 4.1.2 resolution: "@nomicfoundation/ethereumjs-tx@npm:4.1.2" @@ -2552,6 +4457,23 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-tx@npm:5.0.4": + version: 5.0.4 + resolution: "@nomicfoundation/ethereumjs-tx@npm:5.0.4" + dependencies: + "@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" + peerDependencies: + c-kzg: ^2.1.2 + peerDependenciesMeta: + c-kzg: + optional: true + checksum: 1e4ba6d7d6aa8d44a807e3332e98e8fbea70c1aa91be3b39b581c4b498554ee380eec21442d737d2b646c722da306dd1179a5e37747b285b93690aab041d52a7 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-util@npm:8.0.6, @nomicfoundation/ethereumjs-util@npm:^8.0.0-rc.3": version: 8.0.6 resolution: "@nomicfoundation/ethereumjs-util@npm:8.0.6" @@ -2584,6 +4506,33 @@ __metadata: languageName: node linkType: hard +"@nomicfoundation/ethereumjs-util@npm:9.0.4": + version: 9.0.4 + resolution: "@nomicfoundation/ethereumjs-util@npm:9.0.4" + dependencies: + "@nomicfoundation/ethereumjs-rlp": "npm:5.0.4" + ethereum-cryptography: "npm:0.1.3" + 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 + "@nomicfoundation/ethereumjs-vm@npm:7.0.1": version: 7.0.1 resolution: "@nomicfoundation/ethereumjs-vm@npm:7.0.1" @@ -2626,6 +4575,25 @@ __metadata: languageName: node linkType: hard +"@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" + checksum: a1893c8aa0fb8666bcb7371d8a57f641bd6079a79f9e08175aca214cd4a3d7eda3e54046a7d1b4c6cbc2356e80b1e6b44295e56df2d184ceb157eb67e54ee326 + languageName: node + linkType: hard + "@nomicfoundation/ethereumjs-vm@npm:^6.0.0-rc.3": version: 6.4.2 resolution: "@nomicfoundation/ethereumjs-vm@npm:6.4.2" @@ -2770,7 +4738,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: @@ -2815,6 +4783,19 @@ __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" @@ -2844,7 +4825,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 @@ -2889,7 +4870,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: @@ -2930,17 +4911,50 @@ __metadata: version: 1.31.3 resolution: "@openzeppelin/upgrades-core@npm:1.31.3" dependencies: - cbor: "npm:^9.0.0" - chalk: "npm:^4.1.0" - compare-versions: "npm:^6.0.0" - debug: "npm:^4.1.1" - ethereumjs-util: "npm:^7.0.3" - minimist: "npm:^1.2.7" - proper-lockfile: "npm:^4.1.1" - solidity-ast: "npm:^0.4.51" - bin: - openzeppelin-upgrades-core: dist/cli/cli.js - checksum: 7b40bd2cbdb53e76bb3b319b8f70bdcbd6cc473290aa8950dff243603be987456e2ef90f7ca75f7f5b70c5ca652f052d5b9d518d30f5b025fb9b09e5d8624777 + cbor: "npm:^9.0.0" + chalk: "npm:^4.1.0" + compare-versions: "npm:^6.0.0" + debug: "npm:^4.1.1" + ethereumjs-util: "npm:^7.0.3" + minimist: "npm:^1.2.7" + proper-lockfile: "npm:^4.1.1" + solidity-ast: "npm:^0.4.51" + bin: + openzeppelin-upgrades-core: dist/cli/cli.js + checksum: 7b40bd2cbdb53e76bb3b319b8f70bdcbd6cc473290aa8950dff243603be987456e2ef90f7ca75f7f5b70c5ca652f052d5b9d518d30f5b025fb9b09e5d8624777 + 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 @@ -2965,6 +4979,20 @@ __metadata: 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 + "@resolver-engine/core@npm:^0.3.3": version: 0.3.3 resolution: "@resolver-engine/core@npm:0.3.3" @@ -3010,6 +5038,13 @@ __metadata: languageName: node linkType: hard +"@scure/base@npm:^1.1.1": + version: 1.1.5 + resolution: "@scure/base@npm:1.1.5" + checksum: 6eb07be0202fac74a57c79d0d00a45f6f7e57447010c1e3d90a4275d197829727b7abc54b248fc6f9bef9ae374f7be5ee9154dde5b5b73da773560bf17aa8504 + languageName: node + linkType: hard + "@scure/base@npm:~1.1.0": version: 1.1.3 resolution: "@scure/base@npm:1.1.3" @@ -3182,6 +5217,13 @@ __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 + "@szmarczak/http-timer@npm:^1.1.2": version: 1.1.2 resolution: "@szmarczak/http-timer@npm:1.1.2" @@ -3396,7 +5438,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: @@ -3467,13 +5509,20 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.7": +"@types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.7, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db languageName: node linkType: hard +"@types/json5@npm:^0.0.29": + version: 0.0.29 + resolution: "@types/json5@npm:0.0.29" + checksum: 6bf5337bc447b706bb5b4431d37686aa2ea6d07cfd6f79cc31de80170d6ff9b1c7384a9c0ccbc45b3f512bae9e9f75c2e12109806a15331dc94e8a8db6dbb4ac + languageName: node + linkType: hard + "@types/keyv@npm:^3.1.1, @types/keyv@npm:^3.1.4": version: 3.1.4 resolution: "@types/keyv@npm:3.1.4" @@ -3534,6 +5583,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" @@ -3583,6 +5639,15 @@ __metadata: languageName: node linkType: hard +"@types/node@npm:^20.4.2": + version: 20.11.19 + resolution: "@types/node@npm:20.11.19" + dependencies: + undici-types: "npm:~5.26.4" + checksum: f451ef0a1d78f29c57bad7b77e49ebec945f2a6d0d7a89851d7e185ee9fe7ad94d651c0dfbcb7858c9fa791310c8b40a881e2260f56bd3c1b7e7ae92723373ae + languageName: node + linkType: hard + "@types/node@npm:^20.8.7": version: 20.10.1 resolution: "@types/node@npm:20.10.1" @@ -3636,6 +5701,13 @@ __metadata: languageName: node linkType: hard +"@types/qs@npm:^6.9.4": + version: 6.9.11 + resolution: "@types/qs@npm:6.9.11" + checksum: 657a50f05b694d6fd3916d24177cfa0f3b8b87d9deff4ffa4dddcb0b03583ebf7c47b424b8de400270fb9a5cc1e9cf790dd82c833c6935305851e7da8ede3ff5 + languageName: node + linkType: hard + "@types/readable-stream@npm:^2.3.13": version: 2.3.15 resolution: "@types/readable-stream@npm:2.3.15" @@ -3673,6 +5745,13 @@ __metadata: languageName: node linkType: hard +"@types/semver@npm:^7.3.12": + version: 7.5.7 + resolution: "@types/semver@npm:7.5.7" + checksum: fb72d8b86a7779650f14ae89542f1da2ab624adb8188d98754b1d29a2fe3d41f0348bf9435b60ad145df1812fd2a09b3256779aa23b532c199f3dee59619a1eb + languageName: node + linkType: hard + "@types/semver@npm:^7.5.0": version: 7.5.6 resolution: "@types/semver@npm:7.5.6" @@ -3755,6 +5834,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" @@ -3793,6 +5881,30 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/eslint-plugin@npm:^5.20.0": + version: 5.62.0 + resolution: "@typescript-eslint/eslint-plugin@npm:5.62.0" + dependencies: + "@eslint-community/regexpp": "npm:^4.4.0" + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/type-utils": "npm:5.62.0" + "@typescript-eslint/utils": "npm:5.62.0" + debug: "npm:^4.3.4" + graphemer: "npm:^1.4.0" + ignore: "npm:^5.2.0" + natural-compare-lite: "npm:^1.4.0" + semver: "npm:^7.3.7" + tsutils: "npm:^3.21.0" + peerDependencies: + "@typescript-eslint/parser": ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 3f40cb6bab5a2833c3544e4621b9fdacd8ea53420cadc1c63fac3b89cdf5c62be1e6b7bcf56976dede5db4c43830de298ced3db60b5494a3b961ca1b4bff9f2a + 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" @@ -3851,6 +5963,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/parser@npm:^5.20.0": + version: 5.62.0 + resolution: "@typescript-eslint/parser@npm:5.62.0" + dependencies: + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/typescript-estree": "npm:5.62.0" + debug: "npm:^4.3.4" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + typescript: + optional: true + checksum: 315194b3bf39beb9bd16c190956c46beec64b8371e18d6bb72002108b250983eb1e186a01d34b77eb4045f4941acbb243b16155fbb46881105f65e37dc9e24d4 + languageName: node + linkType: hard + "@typescript-eslint/parser@npm:^6.8.0": version: 6.13.1 resolution: "@typescript-eslint/parser@npm:6.13.1" @@ -3879,6 +6008,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/scope-manager@npm:5.62.0" + dependencies: + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/visitor-keys": "npm:5.62.0" + checksum: 861253235576c1c5c1772d23cdce1418c2da2618a479a7de4f6114a12a7ca853011a1e530525d0931c355a8fd237b9cd828fac560f85f9623e24054fd024726f + 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" @@ -3889,6 +6028,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/type-utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/type-utils@npm:5.62.0" + dependencies: + "@typescript-eslint/typescript-estree": "npm:5.62.0" + "@typescript-eslint/utils": "npm:5.62.0" + debug: "npm:^4.3.4" + tsutils: "npm:^3.21.0" + peerDependencies: + eslint: "*" + peerDependenciesMeta: + typescript: + optional: true + checksum: 93112e34026069a48f0484b98caca1c89d9707842afe14e08e7390af51cdde87378df29d213d3bbd10a7cfe6f91b228031b56218515ce077bdb62ddea9d9f474 + 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" @@ -3913,6 +6069,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/types@npm:5.62.0" + checksum: 7febd3a7f0701c0b927e094f02e82d8ee2cada2b186fcb938bc2b94ff6fbad88237afc304cbaf33e82797078bbbb1baf91475f6400912f8b64c89be79bfa4ddf + languageName: node + linkType: hard + "@typescript-eslint/types@npm:6.13.1": version: 6.13.1 resolution: "@typescript-eslint/types@npm:6.13.1" @@ -3938,6 +6101,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/typescript-estree@npm:5.62.0" + dependencies: + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/visitor-keys": "npm:5.62.0" + debug: "npm:^4.3.4" + globby: "npm:^11.1.0" + is-glob: "npm:^4.0.3" + semver: "npm:^7.3.7" + tsutils: "npm:^3.21.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: d7984a3e9d56897b2481940ec803cb8e7ead03df8d9cfd9797350be82ff765dfcf3cfec04e7355e1779e948da8f02bc5e11719d07a596eb1cb995c48a95e38cf + 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" @@ -3956,6 +6137,24 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/utils@npm:5.62.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.2.0" + "@types/json-schema": "npm:^7.0.9" + "@types/semver": "npm:^7.3.12" + "@typescript-eslint/scope-manager": "npm:5.62.0" + "@typescript-eslint/types": "npm:5.62.0" + "@typescript-eslint/typescript-estree": "npm:5.62.0" + eslint-scope: "npm:^5.1.1" + semver: "npm:^7.3.7" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: f09b7d9952e4a205eb1ced31d7684dd55cee40bf8c2d78e923aa8a255318d97279825733902742c09d8690f37a50243f4c4d383ab16bd7aefaf9c4b438f785e1 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:6.13.1": version: 6.13.1 resolution: "@typescript-eslint/utils@npm:6.13.1" @@ -3983,6 +6182,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:5.62.0": + version: 5.62.0 + resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" + dependencies: + "@typescript-eslint/types": "npm:5.62.0" + eslint-visitor-keys: "npm:^3.3.0" + checksum: 7c3b8e4148e9b94d9b7162a596a1260d7a3efc4e65199693b8025c71c4652b8042501c0bc9f57654c1e2943c26da98c0f77884a746c6ae81389fcb0b513d995d + 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" @@ -4046,6 +6255,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" @@ -4260,6 +6529,20 @@ __metadata: languageName: node linkType: hard +"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.10.0, 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" @@ -4272,7 +6555,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: @@ -4304,6 +6587,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" @@ -4510,6 +6802,16 @@ __metadata: languageName: node linkType: hard +"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.5" + is-array-buffer: "npm:^3.0.4" + checksum: f5cdf54527cd18a3d2852ddf73df79efec03829e7373a8322ef5df2b4ef546fb365c19c71d6b42d641cb6bfe0f1a2f19bc0ece5b533295f86d7c3d522f228917 + languageName: node + linkType: hard + "array-flatten@npm:1.1.1": version: 1.1.1 resolution: "array-flatten@npm:1.1.1" @@ -4524,6 +6826,19 @@ __metadata: languageName: node linkType: hard +"array-includes@npm:^3.1.7": + version: 3.1.7 + resolution: "array-includes@npm:3.1.7" + dependencies: + 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-string: "npm:^1.0.7" + checksum: 692907bd7f19d06dc58ccb761f34b58f5dc0b437d2b47a8fe42a1501849a5cf5c27aed3d521a9702667827c2c85a7e75df00a402c438094d87fc43f39ebf9b2b + languageName: node + linkType: hard + "array-union@npm:^2.1.0": version: 2.1.0 resolution: "array-union@npm:2.1.0" @@ -4545,6 +6860,19 @@ __metadata: languageName: node linkType: hard +"array.prototype.filter@npm:^1.0.3": + version: 1.0.3 + resolution: "array.prototype.filter@npm:1.0.3" + dependencies: + call-bind: "npm:^1.0.2" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + es-array-method-boxes-properly: "npm:^1.0.0" + is-string: "npm:^1.0.7" + checksum: 8b70b5f866df5d90fa27aa5bfa30f5fefc44cbea94b0513699d761713658077c2a24cbf06aac5179eabddb6c93adc467af4c288b7a839c5bc5a769ee5a2d48ad + languageName: node + linkType: hard + "array.prototype.findlast@npm:^1.2.2": version: 1.2.3 resolution: "array.prototype.findlast@npm:1.2.3" @@ -4558,7 +6886,20 @@ __metadata: languageName: node linkType: hard -"array.prototype.flat@npm:^1.2.3": +"array.prototype.findlastindex@npm:^1.2.3": + version: 1.2.4 + resolution: "array.prototype.findlastindex@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: b23ae35cf7621c82c20981ee110626090734a264798e781b052e534e3d61d576f03d125d92cf2e3672062bb5cc5907e02e69f2d80196a55f3cdb0197b4aa8c64 + languageName: node + linkType: hard + +"array.prototype.flat@npm:^1.2.3, array.prototype.flat@npm:^1.3.2": version: 1.3.2 resolution: "array.prototype.flat@npm:1.3.2" dependencies: @@ -4570,6 +6911,18 @@ __metadata: languageName: node linkType: hard +"array.prototype.flatmap@npm:^1.3.2": + version: 1.3.2 + resolution: "array.prototype.flatmap@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" + checksum: 67b3f1d602bb73713265145853128b1ad77cc0f9b833c7e1e056b323fbeac41a4ff1c9c99c7b9445903caea924d9ca2450578d9011913191aa88cc3c3a4b54f4 + languageName: node + linkType: hard + "array.prototype.reduce@npm:^1.0.6": version: 1.0.6 resolution: "array.prototype.reduce@npm:1.0.6" @@ -4598,6 +6951,22 @@ __metadata: languageName: node linkType: hard +"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.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: d32754045bcb2294ade881d45140a5e52bda2321b9e98fa514797b7f0d252c4c5ab0d1edb34112652c62fa6a9398def568da63a4d7544672229afea283358c36 + languageName: node + linkType: hard + "arrify@npm:^1.0.1": version: 1.0.1 resolution: "arrify@npm:1.0.1" @@ -4605,7 +6974,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 @@ -4633,6 +7002,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" @@ -4764,6 +7144,13 @@ __metadata: languageName: node linkType: hard +"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.5": version: 1.0.5 resolution: "available-typed-arrays@npm:1.0.5" @@ -4771,6 +7158,15 @@ __metadata: languageName: node linkType: hard +"available-typed-arrays@npm:^1.0.6": + 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 + "aws-sign2@npm:~0.7.0": version: 0.7.0 resolution: "aws-sign2@npm:0.7.0" @@ -5035,6 +7431,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" @@ -5348,6 +7751,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" @@ -5450,6 +7890,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" @@ -5529,7 +7976,7 @@ __metadata: 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 @@ -5716,6 +8163,22 @@ __metadata: languageName: node linkType: hard +"boxen@npm:^5.1.2": + version: 5.1.2 + resolution: "boxen@npm:5.1.2" + dependencies: + 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 + "bplist-parser@npm:^0.2.0": version: 0.2.0 resolution: "bplist-parser@npm:0.2.0" @@ -5889,6 +8352,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" @@ -5918,6 +8395,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" @@ -6005,6 +8491,15 @@ __metadata: languageName: node linkType: hard +"busboy@npm:^1.6.0": + version: 1.6.0 + resolution: "busboy@npm:1.6.0" + dependencies: + streamsearch: "npm:^1.1.0" + checksum: fa7e836a2b82699b6e074393428b91ae579d4f9e21f5ac468e1b459a244341d722d2d22d10920cdd849743dbece6dca11d72de939fb75a7448825cf2babfba1f + languageName: node + linkType: hard + "bytes@npm:3.1.1": version: 3.1.1 resolution: "bytes@npm:3.1.1" @@ -6140,6 +8635,19 @@ __metadata: languageName: node linkType: hard +"call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": + 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.4" + set-function-length: "npm:^1.2.1" + checksum: a3ded2e423b8e2a265983dba81c27e125b48eefb2655e7dfab6be597088da3d47c47976c24bc51b8fd9af1061f8f87b4ab78a314f3c77784b2ae2ba535ad8b8d + languageName: node + linkType: hard + "callsites@npm:^3.0.0": version: 3.1.0 resolution: "callsites@npm:3.1.0" @@ -6147,6 +8655,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" @@ -6172,7 +8690,7 @@ __metadata: 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 @@ -6186,6 +8704,24 @@ __metadata: languageName: node linkType: hard +"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 + "case@npm:^1.6.3": version: 1.6.3 resolution: "case@npm:1.6.3" @@ -6236,6 +8772,21 @@ __metadata: languageName: node linkType: hard +"chai@npm:^4.2.0": + version: 4.4.1 + resolution: "chai@npm:4.4.1" + dependencies: + assertion-error: "npm:^1.1.0" + check-error: "npm:^1.0.3" + deep-eql: "npm:^4.1.3" + get-func-name: "npm:^2.0.2" + loupe: "npm:^2.3.6" + pathval: "npm:^1.1.1" + type-detect: "npm:^4.0.8" + checksum: 91590a8fe18bd6235dece04ccb2d5b4ecec49984b50924499bdcd7a95c02cb1fd2a689407c19bb854497bde534ef57525cfad6c7fdd2507100fd802fbc2aefbd + languageName: node + linkType: hard + "chai@npm:^4.3.10, chai@npm:^4.3.4": version: 4.3.10 resolution: "chai@npm:4.3.10" @@ -6285,6 +8836,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" @@ -6439,6 +9046,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" @@ -6582,6 +9196,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" @@ -6732,6 +9353,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" @@ -6775,6 +9403,13 @@ __metadata: 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" @@ -6784,6 +9419,17 @@ __metadata: 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 + "content-disposition@npm:0.5.4": version: 0.5.4 resolution: "content-disposition@npm:0.5.4" @@ -6850,6 +9496,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" @@ -6949,7 +9602,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: @@ -7047,7 +9700,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: @@ -7176,6 +9829,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" @@ -7213,7 +9880,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:^3.1.0": +"debug@npm:^3.1.0, debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" dependencies: @@ -7383,6 +10050,17 @@ __metadata: languageName: node linkType: hard +"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: + es-define-property: "npm:^1.0.0" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.0.1" + checksum: dea0606d1483eb9db8d930d4eac62ca0fa16738b0b3e07046cddfacf7d8c868bbe13fa0cb263eb91c7d0d527960dc3f2f2471a69ed7816210307f6744fe62e37 + languageName: node + linkType: hard + "define-lazy-prop@npm:^3.0.0": version: 3.0.0 resolution: "define-lazy-prop@npm:3.0.0" @@ -7390,7 +10068,7 @@ __metadata: 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.1.4, define-properties@npm:^1.2.0, define-properties@npm:^1.2.1": version: 1.2.1 resolution: "define-properties@npm:1.2.1" dependencies: @@ -7478,6 +10156,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" @@ -7583,6 +10268,25 @@ __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:^2.1.0": + version: 2.1.0 + resolution: "doctrine@npm:2.1.0" + dependencies: + esutils: "npm:^2.0.2" + checksum: b6416aaff1f380bf56c3b552f31fdf7a69b45689368deca72d28636f41c16bb28ec3ebc40ace97db4c1afc0ceeb8120e8492fe0046841c94c2933b2e30a7d5ac + languageName: node + linkType: hard + "doctrine@npm:^3.0.0": version: 3.0.0 resolution: "doctrine@npm:3.0.0" @@ -7599,6 +10303,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" @@ -7615,6 +10329,13 @@ __metadata: languageName: node linkType: hard +"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 + "dotenv@npm:^9.0.0": version: 9.0.2 resolution: "dotenv@npm:9.0.2" @@ -7640,6 +10361,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" @@ -7690,6 +10418,13 @@ __metadata: languageName: node linkType: hard +"electron-to-chromium@npm:^1.4.668": + version: 1.4.679 + resolution: "electron-to-chromium@npm:1.4.679" + checksum: 6f1385e080360f19ec7b6e9d1072a13325cc110ca6fc10c0bb5f4c427003abecc66074c85509bedae8352ce28557fc26f5a1f238d11f0ee0c481c42a55c9fda4 + languageName: node + linkType: hard + "elliptic@npm:6.5.4, elliptic@npm:^6.4.0, elliptic@npm:^6.5.2, elliptic@npm:^6.5.3, elliptic@npm:^6.5.4": version: 6.5.4 resolution: "elliptic@npm:6.5.4" @@ -7733,6 +10468,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" @@ -7869,6 +10611,55 @@ __metadata: languageName: node linkType: hard +"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.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.4" + get-symbol-description: "npm:^1.0.2" + globalthis: "npm:^1.0.3" + gopd: "npm:^1.0.1" + has-property-descriptors: "npm:^1.0.2" + has-proto: "npm:^1.0.1" + has-symbols: "npm:^1.0.3" + 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.13" + is-weakref: "npm:^1.0.2" + object-inspect: "npm:^1.13.1" + object-keys: "npm:^1.1.1" + 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.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.14" + checksum: dc332c3a010c5e7b77b7ea8a4532ac455fa02e7bcabf996a47447165bafa72d0d99967407d0cf5dbbb5fbbf87f53cd8b706608ec70953523b8cd2b831b9a9d64 + languageName: node + linkType: hard + "es-array-method-boxes-properly@npm:^1.0.0": version: 1.0.0 resolution: "es-array-method-boxes-properly@npm:1.0.0" @@ -7876,6 +10667,22 @@ __metadata: languageName: node linkType: hard +"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.4" + checksum: 6bf3191feb7ea2ebda48b577f69bdfac7a2b3c9bcf97307f55fd6ef1bbca0b49f0c219a935aca506c993d8c5d8bddd937766cb760cd5e5a1071351f2df9f9aa4 + languageName: node + linkType: hard + +"es-errors@npm:^1.0.0, 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.1": version: 2.0.2 resolution: "es-set-tostringtag@npm:2.0.2" @@ -7887,7 +10694,18 @@ __metadata: languageName: node linkType: hard -"es-shim-unscopables@npm:^1.0.0": +"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.2": version: 1.0.2 resolution: "es-shim-unscopables@npm:1.0.2" dependencies: @@ -7993,7 +10811,7 @@ __metadata: languageName: node linkType: hard -"eslint-config-prettier@npm:^8.3.0": +"eslint-config-prettier@npm:^8.3.0, eslint-config-prettier@npm:^8.5.0": version: 8.10.0 resolution: "eslint-config-prettier@npm:8.10.0" peerDependencies: @@ -8015,6 +10833,89 @@ __metadata: languageName: node linkType: hard +"eslint-config-standard@npm:^16.0.3": + version: 16.0.3 + resolution: "eslint-config-standard@npm:16.0.3" + peerDependencies: + eslint: ^7.12.1 + eslint-plugin-import: ^2.22.1 + eslint-plugin-node: ^11.1.0 + eslint-plugin-promise: ^4.2.1 || ^5.0.0 + checksum: 6c7276b15329c3ed3c516b442b99cab9b30cb750a58b3bc6994574103f843bf7ea4f7e86bb815c206a610b12fb765d9cd283e45580f9e8549c6d9510fc8177c5 + languageName: node + linkType: hard + +"eslint-import-resolver-node@npm:^0.3.9": + version: 0.3.9 + resolution: "eslint-import-resolver-node@npm:0.3.9" + dependencies: + debug: "npm:^3.2.7" + is-core-module: "npm:^2.13.0" + resolve: "npm:^1.22.4" + checksum: 0ea8a24a72328a51fd95aa8f660dcca74c1429806737cf10261ab90cfcaaf62fd1eff664b76a44270868e0a932711a81b250053942595bcd00a93b1c1575dd61 + languageName: node + linkType: hard + +"eslint-module-utils@npm:^2.8.0": + version: 2.8.0 + resolution: "eslint-module-utils@npm:2.8.0" + dependencies: + debug: "npm:^3.2.7" + peerDependenciesMeta: + eslint: + optional: true + checksum: c7a8d1a58d76ec8217a8fea49271ec8132d1b9390965a75f6a4ecbc9e5983d742195b46d2e4378231d2186801439fe1aa5700714b0bfd4eb17aac6e1b65309df + languageName: node + linkType: hard + +"eslint-plugin-es@npm:^3.0.0": + version: 3.0.1 + resolution: "eslint-plugin-es@npm:3.0.1" + dependencies: + eslint-utils: "npm:^2.0.0" + regexpp: "npm:^3.0.0" + peerDependencies: + eslint: ">=4.19.1" + checksum: 12ae730aa9603e680af048e1653aac15e529411b68b8d0da6e290700b17c695485af7c3f5360f531f80970786cab7288c2c1d4a58c35ec1bb89649897c016c4a + languageName: node + linkType: hard + +"eslint-plugin-import@npm:^2.22.0": + version: 2.29.1 + resolution: "eslint-plugin-import@npm:2.29.1" + dependencies: + array-includes: "npm:^3.1.7" + array.prototype.findlastindex: "npm:^1.2.3" + array.prototype.flat: "npm:^1.3.2" + array.prototype.flatmap: "npm:^1.3.2" + debug: "npm:^3.2.7" + doctrine: "npm:^2.1.0" + eslint-import-resolver-node: "npm:^0.3.9" + eslint-module-utils: "npm:^2.8.0" + hasown: "npm:^2.0.0" + is-core-module: "npm:^2.13.1" + is-glob: "npm:^4.0.3" + minimatch: "npm:^3.1.2" + object.fromentries: "npm:^2.0.7" + object.groupby: "npm:^1.0.1" + object.values: "npm:^1.1.7" + semver: "npm:^6.3.1" + tsconfig-paths: "npm:^3.15.0" + peerDependencies: + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + checksum: 5f35dfbf4e8e67f741f396987de9504ad125c49f4144508a93282b4ea0127e052bde65ab6def1f31b6ace6d5d430be698333f75bdd7dca3bc14226c92a083196 + languageName: node + linkType: hard + +"eslint-plugin-mocha-no-only@npm:^1.1.1": + version: 1.1.1 + resolution: "eslint-plugin-mocha-no-only@npm:1.1.1" + dependencies: + requireindex: "npm:~1.1.0" + checksum: 7b5c9c79ade467436592d4d9abc23fa400fa6d41ced1d4926e6f0b3dd810ac4a5f9bbcf82daf2936ab949d403941ceb3474ee9adba90ef651617d615d5e7ad51 + 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" @@ -8029,6 +10930,22 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-node@npm:^11.1.0": + version: 11.1.0 + resolution: "eslint-plugin-node@npm:11.1.0" + dependencies: + eslint-plugin-es: "npm:^3.0.0" + eslint-utils: "npm:^2.0.0" + ignore: "npm:^5.1.1" + minimatch: "npm:^3.0.4" + resolve: "npm:^1.10.1" + semver: "npm:^6.1.0" + peerDependencies: + eslint: ">=5.16.0" + checksum: c7716adac4020cb852fd2410dcd8bdb13a227004de77f96d7f9806d0cf2274f24e0920a7ca73bcd72d90003696c1f17fdd9fe3ca218e64ee03dc2b840e4416fa + languageName: node + linkType: hard + "eslint-plugin-prettier@npm:^3.4.0": version: 3.4.1 resolution: "eslint-plugin-prettier@npm:3.4.1" @@ -8044,6 +10961,21 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-prettier@npm:^4.0.0": + version: 4.2.1 + resolution: "eslint-plugin-prettier@npm:4.2.1" + dependencies: + prettier-linter-helpers: "npm:^1.0.0" + peerDependencies: + eslint: ">=7.28.0" + prettier: ">=2.0.0" + peerDependenciesMeta: + eslint-config-prettier: + optional: true + checksum: c5e7316baeab9d96ac39c279f16686e837277e5c67a8006c6588bcff317edffdc1532fb580441eb598bc6770f6444006756b68a6575dff1cd85ebe227252d0b7 + languageName: node + linkType: hard + "eslint-plugin-prettier@npm:^5.0.1": version: 5.0.1 resolution: "eslint-plugin-prettier@npm:5.0.1" @@ -8063,6 +10995,24 @@ __metadata: languageName: node linkType: hard +"eslint-plugin-promise@npm:^6.0.0": + version: 6.1.1 + resolution: "eslint-plugin-promise@npm:6.1.1" + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + checksum: ec705741c110cd1cb4d702776e1c7f7fe60b671b71f706c88054ab443cf2767aae5a663928fb426373ba1095eaeda312a740a4f880546631f0e0727f298b3393 + languageName: node + linkType: hard + +"eslint-plugin-standard@npm:5.0.0": + version: 5.0.0 + resolution: "eslint-plugin-standard@npm:5.0.0" + peerDependencies: + eslint: ">=5.0.0" + checksum: 563835504443b6f1feafca6a1f4b35a827bd9e36d9d358f6f8ce9d375951abdf45e4949b34e795da952a822919109420fc4a2c3cc339d2500b6c26789a0617ea + languageName: node + linkType: hard + "eslint-scope@npm:^5.1.1": version: 5.1.1 resolution: "eslint-scope@npm:5.1.1" @@ -8083,7 +11033,7 @@ __metadata: languageName: node linkType: hard -"eslint-utils@npm:^2.1.0": +"eslint-utils@npm:^2.0.0, eslint-utils@npm:^2.1.0": version: 2.1.0 resolution: "eslint-utils@npm:2.1.0" dependencies: @@ -8174,6 +11124,54 @@ __metadata: languageName: node linkType: hard +"eslint@npm:^8.13.0": + version: 8.56.0 + resolution: "eslint@npm:8.56.0" + dependencies: + "@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.3.2" + doctrine: "npm:^3.0.0" + escape-string-regexp: "npm:^4.0.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" + 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" + 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.1.2" + natural-compare: "npm:^1.4.0" + optionator: "npm:^0.9.3" + strip-ansi: "npm:^6.0.1" + text-table: "npm:^0.2.0" + bin: + eslint: bin/eslint.js + checksum: 2be598f7da1339d045ad933ffd3d4742bee610515cd2b0d9a2b8b729395a01d4e913552fff555b559fccaefd89d7b37632825789d1b06470608737ae69ab43fb + languageName: node + linkType: hard + "eslint@npm:^8.52.0": version: 8.54.0 resolution: "eslint@npm:8.54.0" @@ -8560,7 +11558,7 @@ __metadata: 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: @@ -8913,7 +11911,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: @@ -9229,6 +12227,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" @@ -9259,6 +12264,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" @@ -9307,6 +12319,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" @@ -9314,6 +12335,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" @@ -9330,6 +12360,37 @@ __metadata: 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 + "fecha@npm:^4.2.0": version: 4.2.3 resolution: "fecha@npm:4.2.3" @@ -9346,6 +12407,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" @@ -9527,6 +12608,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" @@ -9560,6 +12650,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" @@ -9870,6 +12967,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" @@ -9903,6 +13007,19 @@ __metadata: languageName: node linkType: hard +"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: 0a9b82c16696ed6da5e39b1267104475c47e3a9bdbe8b509dfe1710946e38a87be70d759f4bb3cda042d76a41ef47fe769660f3b7c0d1f68750299344ffb15b7 + languageName: node + linkType: hard + "get-iterator@npm:^1.0.2": version: 1.0.2 resolution: "get-iterator@npm:1.0.2" @@ -9959,6 +13076,17 @@ __metadata: languageName: node linkType: hard +"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.5" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.4" + checksum: 867be6d63f5e0eb026cb3b0ef695ec9ecf9310febb041072d2e142f260bd91ced9eeb426b3af98791d1064e324e653424afa6fd1af17dee373bea48ae03162bc + languageName: node + linkType: hard + "get-value@npm:^2.0.3, get-value@npm:^2.0.6": version: 2.0.6 resolution: "get-value@npm:2.0.6" @@ -10034,7 +13162,7 @@ __metadata: languageName: node linkType: hard -"glob@npm:^10.2.2, glob@npm:^10.3.10": +"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: @@ -10062,7 +13190,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: @@ -10128,6 +13256,13 @@ __metadata: languageName: node linkType: hard +"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, globals@npm:^13.6.0, globals@npm:^13.9.0": version: 13.23.0 resolution: "globals@npm:13.23.0" @@ -10272,7 +13407,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: @@ -10283,6 +13427,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" @@ -10297,6 +13481,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" @@ -10339,7 +13530,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: @@ -10351,7 +13542,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: @@ -10364,6 +13555,50 @@ __metadata: languageName: node linkType: hard +"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": + 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: 3711ea331bcbbff4d37057cb3de47a9127011e3ee128c2254a68f3b7f12ab2133965cbcfa3a7ce1bba8461f3b1bda1b175c4814a048c8b06b3ad450001d119d8 + languageName: node + linkType: hard + "hardhat-gas-reporter@npm:^1.0.4": version: 1.0.9 resolution: "hardhat-gas-reporter@npm:1.0.9" @@ -10433,6 +13668,74 @@ __metadata: languageName: node linkType: hard +"hardhat@npm:^2.6.1": + 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.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" + "@types/lru-cache": "npm:^5.1.0" + 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" + debug: "npm:^4.1.1" + enquirer: "npm:^2.3.0" + env-paths: "npm:^2.2.0" + ethereum-cryptography: "npm:^1.0.3" + ethereumjs-abi: "npm:^0.6.8" + find-up: "npm:^2.1.0" + fp-ts: "npm:1.19.3" + fs-extra: "npm:^7.0.1" + glob: "npm:7.2.0" + immutable: "npm:^4.0.0-rc.12" + io-ts: "npm:1.10.4" + keccak: "npm:^3.0.2" + lodash: "npm:^4.17.11" + mnemonist: "npm:^0.38.0" + mocha: "npm:^10.0.0" + p-map: "npm:^4.0.0" + raw-body: "npm:^2.4.1" + resolve: "npm:1.17.0" + semver: "npm:^6.3.0" + solc: "npm:0.7.3" + source-map-support: "npm:^0.5.13" + stacktrace-parser: "npm:^0.1.10" + tsort: "npm:0.0.1" + undici: "npm:^5.14.0" + uuid: "npm:^8.3.2" + ws: "npm:^7.4.6" + peerDependencies: + ts-node: "*" + typescript: "*" + peerDependenciesMeta: + ts-node: + optional: true + typescript: + optional: true + bin: + hardhat: internal/cli/bootstrap.js + checksum: e27f1fc6b016d7ceb62795ff47384a02ad61722cdd2ab55c91d7ff2ce31973a1ea5e462431c7033ca53e66e4722c3597664b0ebaac70104622d227e94b4fb3e0 + languageName: node + linkType: hard + "hardhat@npm:^2.6.4": version: 2.19.1 resolution: "hardhat@npm:2.19.1" @@ -10613,6 +13916,15 @@ __metadata: languageName: node linkType: hard +"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: + 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" @@ -10636,6 +13948,15 @@ __metadata: languageName: node linkType: hard +"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.3" + checksum: a8b166462192bafe3d9b6e420a1d581d93dd867adb61be223a17a8d6dad147aa77a8be32c961bb2f27b3ef893cae8d36f564ab651f5e9b7938ae86f74027c48c + languageName: node + linkType: hard + "has-value@npm:^0.3.1": version: 0.3.1 resolution: "has-value@npm:0.3.1" @@ -10693,6 +14014,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" @@ -10722,6 +14050,15 @@ __metadata: languageName: node linkType: hard +"hasown@npm:^2.0.1": + version: 2.0.1 + resolution: "hasown@npm:2.0.1" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 9e27e70e8e4204f4124c8f99950d1ba2b1f5174864fd39ff26da190f9ea6488c1b3927dcc64981c26d1f637a971783c9489d62c829d393ea509e6f1ba20370bb + languageName: node + linkType: hard + "he@npm:1.2.0": version: 1.2.0 resolution: "he@npm:1.2.0" @@ -10731,6 +14068,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" @@ -10789,6 +14136,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" @@ -11003,6 +14357,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" @@ -11017,6 +14378,13 @@ __metadata: 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 + "import-fresh@npm:^3.0.0, import-fresh@npm:^3.2.1, import-fresh@npm:^3.3.0": version: 3.3.0 resolution: "import-fresh@npm:3.3.0" @@ -11027,6 +14395,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" @@ -11072,6 +14454,27 @@ __metadata: 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" @@ -11106,6 +14509,17 @@ __metadata: languageName: node linkType: hard +"internal-slot@npm:^1.0.7": + version: 1.0.7 + resolution: "internal-slot@npm:1.0.7" + dependencies: + es-errors: "npm:^1.3.0" + hasown: "npm:^2.0.0" + side-channel: "npm:^1.0.4" + checksum: f8b294a4e6ea3855fc59551bbf35f2b832cf01fd5e6e2a97f5c201a071cc09b49048f856e484b67a6c721da5e55736c5b6ddafaf19e2dbeb4a3ff1821680de6c + languageName: node + linkType: hard + "interpret@npm:^1.0.0": version: 1.4.0 resolution: "interpret@npm:1.4.0" @@ -11113,7 +14527,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: @@ -11285,6 +14699,16 @@ __metadata: 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 + "is-accessor-descriptor@npm:^1.0.1": version: 1.0.1 resolution: "is-accessor-descriptor@npm:1.0.1" @@ -11315,6 +14739,16 @@ __metadata: languageName: node linkType: hard +"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.1" + checksum: 42a49d006cc6130bc5424eae113e948c146f31f9d24460fc0958f855d9d810e6fd2e4519bf19aab75179af9c298ea6092459d8cafdec523cd19e529b26eab860 + languageName: node + linkType: hard + "is-arrayish@npm:^0.2.1": version: 0.2.1 resolution: "is-arrayish@npm:0.2.1" @@ -11396,7 +14830,7 @@ __metadata: languageName: node linkType: hard -"is-core-module@npm:^2.13.0, is-core-module@npm:^2.5.0": +"is-core-module@npm:^2.13.0, is-core-module@npm:^2.13.1, is-core-module@npm:^2.5.0": version: 2.13.1 resolution: "is-core-module@npm:2.13.1" dependencies: @@ -11594,6 +15028,15 @@ __metadata: languageName: node linkType: hard +"is-lower-case@npm:^2.0.2": + version: 2.0.2 + 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.2 resolution: "is-negative-zero@npm:2.0.2" @@ -11687,6 +15130,15 @@ __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" @@ -11757,8 +15209,17 @@ __metadata: version: 1.1.12 resolution: "is-typed-array@npm:1.1.12" dependencies: - which-typed-array: "npm:^1.1.11" - checksum: 9863e9cc7223c6fc1c462a2c3898a7beff6b41b1ee0fabb03b7d278ae7de670b5bcbc8627db56bb66ed60902fa37d53fe5cce0fd2f7d73ac64fe5da6f409b6ae + which-typed-array: "npm:^1.1.11" + checksum: 9863e9cc7223c6fc1c462a2c3898a7beff6b41b1ee0fabb03b7d278ae7de670b5bcbc8627db56bb66ed60902fa37d53fe5cce0fd2f7d73ac64fe5da6f409b6ae + languageName: node + linkType: hard + +"is-typed-array@npm:^1.1.13": + version: 1.1.13 + resolution: "is-typed-array@npm:1.1.13" + dependencies: + which-typed-array: "npm:^1.1.14" + checksum: fa5cb97d4a80e52c2cc8ed3778e39f175a1a2ae4ddf3adae3187d69586a1fd57cfa0b095db31f66aa90331e9e3da79184cea9c6abdcd1abc722dc3c3edd51cca languageName: node linkType: hard @@ -11769,6 +15230,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" @@ -11776,6 +15246,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" @@ -11799,7 +15278,7 @@ __metadata: languageName: node linkType: hard -"is-windows@npm:^1.0.0, 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 @@ -11900,6 +15379,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" @@ -12103,6 +15591,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" @@ -12112,6 +15609,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" @@ -12133,6 +15637,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" @@ -12163,6 +15676,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" @@ -12228,6 +15752,26 @@ __metadata: languageName: node linkType: hard +"json5@npm:^1.0.2": + version: 1.0.2 + resolution: "json5@npm:1.0.2" + dependencies: + minimist: "npm:^1.2.0" + bin: + json5: lib/cli.js + checksum: 9ee316bf21f000b00752e6c2a3b79ecf5324515a5c60ee88983a1910a45426b643a4f3461657586e8aeca87aaf96f0a519b0516d2ae527a6c3e7eed80f68717f + 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" @@ -12627,6 +16171,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" @@ -12705,6 +16258,15 @@ __metadata: 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" @@ -12747,6 +16309,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" @@ -12754,6 +16323,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" @@ -12817,6 +16393,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" @@ -12845,7 +16428,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 @@ -12922,6 +16505,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" @@ -12952,6 +16553,13 @@ __metadata: languageName: node linkType: hard +"lru-cache@npm:^10.0.0": + version: 10.2.0 + resolution: "lru-cache@npm:10.2.0" + checksum: c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee + 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" @@ -12987,6 +16595,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" @@ -13034,7 +16649,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 @@ -13071,6 +16686,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" @@ -13248,6 +16870,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" @@ -13571,7 +17205,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: @@ -13876,6 +17510,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" @@ -13950,6 +17595,13 @@ __metadata: languageName: node linkType: hard +"natural-compare-lite@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare-lite@npm:1.4.0" + checksum: f6cef26f5044515754802c0fc475d81426f3b90fe88c20fabe08771ce1f736ce46e0397c10acb569a4dd0acb84c7f1ee70676122f95d5bfdd747af3a6c6bbaa8 + languageName: node + linkType: hard + "natural-compare@npm:^1.4.0": version: 1.4.0 resolution: "natural-compare@npm:1.4.0" @@ -13992,6 +17644,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" @@ -14079,6 +17741,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" @@ -14132,6 +17808,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" @@ -14171,6 +17856,13 @@ __metadata: languageName: node linkType: hard +"nullthrows@npm:^1.1.1": + version: 1.1.1 + resolution: "nullthrows@npm:1.1.1" + checksum: 56f34bd7c3dcb3bd23481a277fa22918120459d3e9d95ca72976c72e9cac33a97483f0b95fc420e2eb546b9fe6db398273aba9a938650cdb8c98ee8f159dcb30 + languageName: node + linkType: hard + "number-is-nan@npm:^1.0.0": version: 1.0.1 resolution: "number-is-nan@npm:1.0.1" @@ -14213,6 +17905,13 @@ __metadata: languageName: node linkType: hard +"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, object-inspect@npm:^1.9.0": version: 1.13.1 resolution: "object-inspect@npm:1.13.1" @@ -14272,6 +17971,29 @@ __metadata: languageName: node linkType: hard +"object.assign@npm:^4.1.5": + version: 4.1.5 + resolution: "object.assign@npm:4.1.5" + dependencies: + 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: 60108e1fa2706f22554a4648299b0955236c62b3685c52abf4988d14fffb0e7731e00aa8c6448397e3eb63d087dcc124a9f21e1980f36d0b2667f3c18bacd469 + languageName: node + linkType: hard + +"object.fromentries@npm:^2.0.7": + version: 2.0.7 + resolution: "object.fromentries@npm:2.0.7" + dependencies: + call-bind: "npm:^1.0.2" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + checksum: 071745c21f6fc9e6c914691f2532c1fb60ad967e5ddc52801d09958b5de926566299d07ae14466452a7efd29015f9145d6c09c573d93a0dc6f1683ee0ec2b93b + languageName: node + linkType: hard + "object.getownpropertydescriptors@npm:^2.1.6": version: 2.1.7 resolution: "object.getownpropertydescriptors@npm:2.1.7" @@ -14285,6 +18007,19 @@ __metadata: languageName: node linkType: hard +"object.groupby@npm:^1.0.1": + version: 1.0.2 + resolution: "object.groupby@npm:1.0.2" + dependencies: + array.prototype.filter: "npm:^1.0.3" + call-bind: "npm:^1.0.5" + define-properties: "npm:^1.2.1" + es-abstract: "npm:^1.22.3" + es-errors: "npm:^1.0.0" + checksum: b6266b1cfec7eb784b8bbe0bca5dc4b371cf9dd3e601b0897d72fa97a5934273d8fb05b3fc5222204104dbec32b50e25ba27e05ad681f71fb739cc1c7e9b81b1 + languageName: node + linkType: hard + "object.pick@npm:^1.3.0": version: 1.3.0 resolution: "object.pick@npm:1.3.0" @@ -14294,6 +18029,17 @@ __metadata: languageName: node linkType: hard +"object.values@npm:^1.1.7": + version: 1.1.7 + resolution: "object.values@npm:1.1.7" + dependencies: + call-bind: "npm:^1.0.2" + define-properties: "npm:^1.2.0" + es-abstract: "npm:^1.22.1" + checksum: e869d6a37fb7afdd0054dea49036d6ccebb84854a8848a093bbd1bc516f53e690bba88f0bc3e83fdfa74c601469ee6989c9b13359cda9604144c6e732fad3b6b + languageName: node + linkType: hard + "obliterator@npm:^2.0.0": version: 2.0.4 resolution: "obliterator@npm:2.0.4" @@ -14409,6 +18155,13 @@ __metadata: languageName: node linkType: hard +"openapi-types@npm:^12.1.0": + version: 12.1.3 + resolution: "openapi-types@npm:12.1.3" + checksum: 4ad4eb91ea834c237edfa6ab31394e87e00c888fc2918009763389c00d02342345195d6f302d61c3fd807f17723cd48df29b47b538b68375b3827b3758cd520f + languageName: node + linkType: hard + "optionator@npm:^0.8.1": version: 0.8.3 resolution: "optionator@npm:0.8.3" @@ -14538,6 +18291,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" @@ -14556,15 +18318,6 @@ __metadata: 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 - languageName: node - linkType: hard - "p-locate@npm:^2.0.0": version: 2.0.0 resolution: "p-locate@npm:2.0.0" @@ -14608,7 +18361,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: @@ -14648,6 +18401,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" @@ -14684,6 +18447,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" @@ -14719,6 +18493,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" @@ -14772,13 +18556,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" @@ -14837,6 +18631,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" @@ -15161,6 +18971,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" @@ -15263,7 +19080,20 @@ __metadata: languageName: node linkType: hard -"prettier@npm:^2.1.2, prettier@npm:^2.2.1, prettier@npm:^2.7.1, prettier@npm:^2.8.3": +"prettier-plugin-solidity@npm:^1.0.0-alpha.56": + version: 1.3.1 + resolution: "prettier-plugin-solidity@npm:1.3.1" + dependencies: + "@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: 6c83bec93a12a172aeae360bca571ffba5659a679d24d9a4905c4cae9f237a2a3c544a78f5efb7f2cd086733e114ed9e031d448799ca7b9f574e8fc07b94323a + languageName: node + linkType: hard + +"prettier@npm:^2.1.1, prettier@npm:^2.1.2, prettier@npm:^2.2.1, prettier@npm:^2.7.1, prettier@npm:^2.8.3": version: 2.8.8 resolution: "prettier@npm:2.8.8" bin: @@ -15361,6 +19191,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" @@ -15551,7 +19390,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 @@ -15565,6 +19404,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" @@ -15588,7 +19443,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: @@ -15705,15 +19560,38 @@ __metadata: languageName: node linkType: hard -"raw-body@npm:2.5.2, raw-body@npm:^2.4.1": - version: 2.5.2 - resolution: "raw-body@npm:2.5.2" - dependencies: - bytes: "npm:3.1.2" - http-errors: "npm:2.0.0" - iconv-lite: "npm:0.4.24" - unpipe: "npm:1.0.0" - checksum: b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4 +"raw-body@npm:2.5.2, raw-body@npm:^2.4.1": + version: 2.5.2 + resolution: "raw-body@npm:2.5.2" + dependencies: + bytes: "npm:3.1.2" + http-errors: "npm:2.0.0" + iconv-lite: "npm:0.4.24" + unpipe: "npm:1.0.0" + checksum: b201c4b66049369a60e766318caff5cb3cc5a900efd89bdac431463822d976ad0670912c931fdbdcf5543207daf6f6833bca57aa116e1661d2ea91e12ca692c4 + 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 @@ -15929,7 +19807,19 @@ __metadata: languageName: node linkType: hard -"regexpp@npm:^3.1.0": +"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.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 + +"regexpp@npm:^3.0.0, regexpp@npm:^3.1.0": version: 3.2.0 resolution: "regexpp@npm:3.2.0" checksum: d1da82385c8754a1681416b90b9cca0e21b4a2babef159099b88f640637d789c69011d0bc94705dacab85b81133e929d027d85210e8b8b03f8035164dbc14710 @@ -15965,6 +19855,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" @@ -16069,6 +19977,13 @@ __metadata: languageName: node linkType: hard +"requireindex@npm:~1.1.0": + version: 1.1.0 + resolution: "requireindex@npm:1.1.0" + checksum: 4d57e7c6d160c4d043a233a6a95a22c792ada72ff378c5ebd415be505b328f3c719f9188dd100f8fcaa8af513a85f39eee0a5047838d715e22e79544a3b7d002 + languageName: node + linkType: hard + "reset@npm:^0.1.0": version: 0.1.0 resolution: "reset@npm:0.1.0" @@ -16136,7 +20051,7 @@ __metadata: languageName: node linkType: hard -"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.8.1, resolve@npm:~1.22.6": +"resolve@npm:^1.1.6, resolve@npm:^1.10.0, resolve@npm:^1.10.1, resolve@npm:^1.22.4, resolve@npm:^1.8.1, resolve@npm:~1.22.6": version: 1.22.8 resolution: "resolve@npm:1.22.8" dependencies: @@ -16165,7 +20080,7 @@ __metadata: languageName: node linkType: hard -"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.8.1#optional!builtin, resolve@patch:resolve@npm%3A~1.22.6#optional!builtin": +"resolve@patch:resolve@npm%3A^1.1.6#optional!builtin, resolve@patch:resolve@npm%3A^1.10.0#optional!builtin, resolve@patch:resolve@npm%3A^1.10.1#optional!builtin, resolve@patch:resolve@npm%3A^1.22.4#optional!builtin, resolve@patch:resolve@npm%3A^1.8.1#optional!builtin, resolve@patch:resolve@npm%3A~1.22.6#optional!builtin": version: 1.22.8 resolution: "resolve@patch:resolve@npm%3A1.22.8#optional!builtin::version=1.22.8&hash=c3c19d" dependencies: @@ -16248,6 +20163,13 @@ __metadata: languageName: node linkType: hard +"rfdc@npm:^1.2.0": + version: 1.3.1 + resolution: "rfdc@npm:1.3.1" + checksum: 69f65e3ed30970f8055fac9fbbef9ce578800ca19554eab1dcbffe73a4b8aef536bc4248313889cf25e3b4e38b212c721eabe30856575bf2b2bc3d90f8ba93ef + languageName: node + linkType: hard + "rfdc@npm:^1.3.0": version: 1.3.0 resolution: "rfdc@npm:1.3.0" @@ -16277,6 +20199,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" @@ -16343,6 +20276,22 @@ __metadata: 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 + "rustbn.js@npm:~0.2.0": version: 0.2.0 resolution: "rustbn.js@npm:0.2.0" @@ -16350,7 +20299,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: @@ -16380,6 +20329,18 @@ __metadata: languageName: node linkType: hard +"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.5" + get-intrinsic: "npm:^1.2.2" + has-symbols: "npm:^1.0.3" + isarray: "npm:^2.0.5" + checksum: 833d3d950fc7507a60075f9bfaf41ec6dac7c50c7a9d62b1e6b071ecc162185881f92e594ff95c1a18301c881352dd6fd236d56999d5819559db7b92da9c28af + languageName: node + linkType: hard + "safe-buffer@npm:5.1.2, safe-buffer@npm:~5.1.0, safe-buffer@npm:~5.1.1": version: 5.1.2 resolution: "safe-buffer@npm:5.1.2" @@ -16414,6 +20375,17 @@ __metadata: languageName: node linkType: hard +"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.6" + es-errors: "npm:^1.3.0" + is-regex: "npm:^1.1.4" + checksum: 900bf7c98dc58f08d8523b7012b468e4eb757afa624f198902c0643d7008ba777b0bdc35810ba0b758671ce887617295fb742b3f3968991b178ceca54cb07603 + languageName: node + linkType: hard + "safe-regex@npm:^1.1.0": version: 1.1.0 resolution: "safe-regex@npm:1.1.0" @@ -16537,7 +20509,7 @@ __metadata: languageName: node linkType: hard -"semver@npm:^6.3.0": +"semver@npm:^6.1.0, semver@npm:^6.3.0, semver@npm:^6.3.1": version: 6.3.1 resolution: "semver@npm:6.3.1" bin: @@ -16546,6 +20518,17 @@ __metadata: languageName: node linkType: hard +"semver@npm:^7.3.7": + version: 7.6.0 + resolution: "semver@npm:7.6.0" + dependencies: + lru-cache: "npm:^6.0.0" + bin: + semver: bin/semver.js + checksum: fbfe717094ace0aa8d6332d7ef5ce727259815bd8d8815700853f4faf23aacbd7192522f0dc5af6df52ef4fa85a355ebd2f5d39f554bd028200d6cf481ab9b53 + languageName: node + linkType: hard + "semver@npm:~5.4.1": version: 5.4.1 resolution: "semver@npm:5.4.1" @@ -16597,6 +20580,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" @@ -16753,6 +20747,20 @@ __metadata: languageName: node linkType: hard +"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.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.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" @@ -16764,6 +20772,18 @@ __metadata: languageName: node linkType: hard +"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.1.4" + es-errors: "npm:^1.3.0" + functions-have-names: "npm:^1.2.3" + has-property-descriptors: "npm:^1.0.2" + checksum: fce59f90696c450a8523e754abb305e2b8c73586452619c2bad5f7bf38c7b6b4651895c9db895679c5bef9554339cf3ef1c329b66ece3eda7255785fbe299316 + languageName: node + linkType: hard + "set-immediate-shim@npm:^1.0.1": version: 1.0.1 resolution: "set-immediate-shim@npm:1.0.1" @@ -16905,6 +20925,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" @@ -17005,6 +21032,16 @@ __metadata: 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" @@ -17126,7 +21163,7 @@ __metadata: languageName: node linkType: hard -"solhint@npm:^3.3.6": +"solhint@npm:^3.3.6, solhint@npm:^3.3.7": version: 3.6.2 resolution: "solhint@npm:3.6.2" dependencies: @@ -17173,6 +21210,13 @@ __metadata: languageName: node linkType: hard +"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 + "solidity-coverage@npm:^0.7.16": version: 0.7.22 resolution: "solidity-coverage@npm:0.7.22" @@ -17351,6 +21395,15 @@ __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.0.2": version: 1.0.3 resolution: "sprintf-js@npm:1.0.3" @@ -17470,6 +21523,13 @@ __metadata: 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" @@ -17484,7 +21544,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: @@ -17746,6 +21806,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" @@ -17997,6 +22066,22 @@ __metadata: languageName: node linkType: hard +"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 + "titleize@npm:^3.0.0": version: 3.0.0 resolution: "titleize@npm:3.0.0" @@ -18029,6 +22114,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" @@ -18128,6 +22220,13 @@ __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" @@ -18219,6 +22318,29 @@ __metadata: languageName: node linkType: hard +"tsconfig-paths@npm:^3.15.0": + version: 3.15.0 + resolution: "tsconfig-paths@npm:3.15.0" + dependencies: + "@types/json5": "npm:^0.0.29" + json5: "npm:^1.0.2" + minimist: "npm:^1.2.6" + strip-bom: "npm:^3.0.0" + checksum: 5b4f301a2b7a3766a986baf8fc0e177eb80bdba6e396792ff92dc23b5bca8bb279fc96517dcaaef63a3b49bebc6c4c833653ec58155780bc906bdbcf7dda0ef5 + 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": version: 1.14.1 resolution: "tslib@npm:1.14.1" @@ -18226,13 +22348,27 @@ __metadata: 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.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" @@ -18446,6 +22582,17 @@ __metadata: languageName: node linkType: hard +"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.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" @@ -18498,7 +22645,7 @@ __metadata: languageName: node linkType: hard -"typescript@npm:^4.7.4": +"typescript@npm:^4.0.2, typescript@npm:^4.7.4": version: 4.9.5 resolution: "typescript@npm:4.9.5" bin: @@ -18508,6 +22655,16 @@ __metadata: languageName: node linkType: hard +"typescript@npm:^5.0.4": + version: 5.3.3 + resolution: "typescript@npm:5.3.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: e33cef99d82573624fc0f854a2980322714986bc35b9cb4d1ce736ed182aeab78e2cb32b385efa493b2a976ef52c53e20d6c6918312353a91850e2b76f1ea44f + languageName: node + linkType: hard + "typescript@npm:^5.1.6": version: 5.3.2 resolution: "typescript@npm:5.3.2" @@ -18518,7 +22675,7 @@ __metadata: 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: @@ -18528,6 +22685,16 @@ __metadata: languageName: node linkType: hard +"typescript@patch:typescript@npm%3A^5.0.4#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: 1d0a5f4ce496c42caa9a30e659c467c5686eae15d54b027ee7866744952547f1be1262f2d40de911618c242b510029d51d43ff605dba8fb740ec85ca2d3f9500 + 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" @@ -18568,6 +22735,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" @@ -18624,6 +22798,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" @@ -18705,6 +22886,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" @@ -18736,6 +22926,38 @@ __metadata: languageName: node linkType: hard +"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 + "uri-js@npm:^4.2.2": version: 4.4.1 resolution: "uri-js@npm:4.4.1" @@ -18778,6 +23000,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" @@ -18918,6 +23147,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" @@ -18972,6 +23208,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" @@ -19838,6 +24081,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" @@ -19947,6 +24203,19 @@ __metadata: languageName: node linkType: hard +"which-typed-array@npm:^1.1.14": + version: 1.1.14 + resolution: "which-typed-array@npm:1.1.14" + dependencies: + 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.1" + checksum: 0960f1e77807058819451b98c51d4cd72031593e8de990b24bd3fc22e176f5eee22921d68d852297c786aec117689f0423ed20aa4fde7ce2704d680677891f56 + languageName: node + linkType: hard + "which@npm:^1.1.1, which@npm:^1.2.9, which@npm:^1.3.1": version: 1.3.1 resolution: "which@npm:1.3.1" @@ -19980,6 +24249,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" @@ -20128,6 +24406,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" @@ -20163,6 +24456,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" @@ -20355,7 +24663,7 @@ __metadata: languageName: node linkType: hard -"yargs@npm:^15.1.0": +"yargs@npm:^15.1.0, yargs@npm:^15.3.1": version: 15.4.1 resolution: "yargs@npm:15.4.1" dependencies: @@ -20424,3 +24732,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