diff --git a/.github/workflows/deploy-subgraph-theGraph.yml b/.github/workflows/deploy-subgraph-theGraph.yml new file mode 100644 index 00000000..ba1f9107 --- /dev/null +++ b/.github/workflows/deploy-subgraph-theGraph.yml @@ -0,0 +1,33 @@ +name: Prod Deploy Subgraph +on: + workflow_dispatch: +jobs: + deploy-subgraph: + name: Deploy subgraph workflow + runs-on: ubuntu-latest + environment: production + steps: + - uses: actions/checkout@v3 + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: "16" + + - name: Install the graph cli + run: npm install @graphprotocol/graph-cli + + - name: Authenticate with prod subgraph + run: | + npx graph auth --product hosted-service ${{ secrets.PROD_SUBGRAPH_API_KEY }} + + - name: Install subgraph dependencies + working-directory: ./subgraph + run: npm install + + - name: Prepare for subgraph deployment + working-directory: ./subgraph + run: npm run prepare + + - name: Deploy subgraph + working-directory: ./subgraph + run: npm run deploy-theGraph diff --git a/.gitignore b/.gitignore index 89d00dd2..22e15e7d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ scripts/data/* yarn-error.log layout-compare/ test/migration/data/t* -releases/*/local/* \ No newline at end of file +releases/*/local/* diff --git a/package.json b/package.json index 4c2db6b3..617372c1 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "coverage": "yarn hardhat coverage --testfiles 'test/' --solcoverjs .solcover.js", "lint": "npm run lint:solidity && npm run lint:javascript", "lint:javascript": "eslint ./", - "test": "hardhat test" + "test": "hardhat test", + "unlock:propose": "node scripts/unlock-admin/propose.js" }, "repository": { "type": "git", @@ -55,6 +56,7 @@ "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.4", "hardhat-log-remover": "^2.0.2", + "js-yaml": "^4.1.0", "lodash": "^4.17.21", "prettier": "^2.5.1", "prettier-plugin-solidity": "^1.0.0-beta.19", diff --git a/scripts/unlock-admin/README.md b/scripts/unlock-admin/README.md new file mode 100644 index 00000000..d197f34c --- /dev/null +++ b/scripts/unlock-admin/README.md @@ -0,0 +1,13 @@ +# Unlock admin proposals + +This is useful to us when we want to create Unlock admin proposals for the council multisig to sign. + +To create Unlock admin proposals: +1. Get a team API key from Defender and set it inside the project root `.env` file. +``` +DEFENDER_API_KEY= +DEFENDER_SECRET_KEY= +``` +2. Create a new proposal file (like in scripts/unlock-admin/example.yaml). +3. At the project root, do `npm run unlock:propose -- `. +4. Follow the links in the output to verify that the proposals were created in Defender. diff --git a/scripts/unlock-admin/abis/PublicLock.json b/scripts/unlock-admin/abis/PublicLock.json new file mode 100644 index 00000000..75fb9928 --- /dev/null +++ b/scripts/unlock-admin/abis/PublicLock.json @@ -0,0 +1 @@ +[{"inputs":[],"name":"CANNOT_APPROVE_SELF","type":"error"},{"inputs":[],"name":"CANT_BE_SMALLER_THAN_SUPPLY","type":"error"},{"inputs":[],"name":"CANT_EXTEND_NON_EXPIRING_KEY","type":"error"},{"inputs":[],"name":"GAS_REFUND_FAILED","type":"error"},{"inputs":[],"name":"INSUFFICIENT_ERC20_VALUE","type":"error"},{"inputs":[],"name":"INSUFFICIENT_VALUE","type":"error"},{"inputs":[],"name":"INVALID_ADDRESS","type":"error"},{"inputs":[{"internalType":"uint8","name":"hookIndex","type":"uint8"}],"name":"INVALID_HOOK","type":"error"},{"inputs":[],"name":"INVALID_LENGTH","type":"error"},{"inputs":[],"name":"INVALID_TOKEN","type":"error"},{"inputs":[],"name":"KEY_NOT_VALID","type":"error"},{"inputs":[],"name":"KEY_TRANSFERS_DISABLED","type":"error"},{"inputs":[],"name":"LOCK_HAS_CHANGED","type":"error"},{"inputs":[],"name":"LOCK_SOLD_OUT","type":"error"},{"inputs":[],"name":"MAX_KEYS_REACHED","type":"error"},{"inputs":[],"name":"MIGRATION_REQUIRED","type":"error"},{"inputs":[],"name":"NON_COMPLIANT_ERC721_RECEIVER","type":"error"},{"inputs":[],"name":"NON_RENEWABLE_LOCK","type":"error"},{"inputs":[],"name":"NOT_ENOUGH_FUNDS","type":"error"},{"inputs":[],"name":"NOT_ENOUGH_TIME","type":"error"},{"inputs":[],"name":"NOT_READY_FOR_RENEWAL","type":"error"},{"inputs":[],"name":"NO_SUCH_KEY","type":"error"},{"inputs":[],"name":"NULL_VALUE","type":"error"},{"inputs":[],"name":"ONLY_KEY_MANAGER_OR_APPROVED","type":"error"},{"inputs":[],"name":"ONLY_LOCK_MANAGER","type":"error"},{"inputs":[],"name":"ONLY_LOCK_MANAGER_OR_KEY_GRANTER","type":"error"},{"inputs":[],"name":"OUT_OF_RANGE","type":"error"},{"inputs":[],"name":"OWNER_CANT_BE_ADDRESS_ZERO","type":"error"},{"inputs":[],"name":"SCHEMA_VERSION_NOT_CORRECT","type":"error"},{"inputs":[],"name":"TRANSFER_TO_SELF","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UNAUTHORIZED","type":"error"},{"inputs":[],"name":"UNAUTHORIZED_KEY_MANAGER_UPDATE","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"sendTo","type":"address"},{"indexed":false,"internalType":"uint256","name":"refund","type":"uint256"}],"name":"CancelKey","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"onKeyPurchaseHook","type":"address"},{"indexed":false,"internalType":"address","name":"onKeyCancelHook","type":"address"},{"indexed":false,"internalType":"address","name":"onValidKeyHook","type":"address"},{"indexed":false,"internalType":"address","name":"onTokenURIHook","type":"address"},{"indexed":false,"internalType":"address","name":"onKeyTransferHook","type":"address"},{"indexed":false,"internalType":"address","name":"onKeyExtendHook","type":"address"},{"indexed":false,"internalType":"address","name":"onKeyGrantHook","type":"address"}],"name":"EventHooksUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newExpiration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bool","name":"timeAdded","type":"bool"}],"name":"ExpirationChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ExpireKey","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"refundValue","type":"uint256"}],"name":"GasRefundValueChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"refundedAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"GasRefunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTimestamp","type":"uint256"}],"name":"KeyExtended","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"KeyGranterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"KeyGranterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"},{"indexed":true,"internalType":"address","name":"_newManager","type":"address"}],"name":"KeyManagerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"updatedRecordsCount","type":"uint256"}],"name":"KeysMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"expirationDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxNumberOfKeys","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxKeysPerAcccount","type":"uint256"}],"name":"LockConfig","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"LockManagerAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"}],"name":"LockManagerRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"string","name":"baseTokenURI","type":"string"}],"name":"LockMetadata","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldKeyPrice","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"keyPrice","type":"uint256"},{"indexed":false,"internalType":"address","name":"oldTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"}],"name":"PricingChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"ReferrerFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"freeTrialLength","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"refundPenaltyBasisPoints","type":"uint256"}],"name":"RefundPenaltyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"transferFeeBasisPoints","type":"uint256"}],"name":"TransferFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lockAddress","type":"address"},{"indexed":false,"internalType":"address","name":"unlockAddress","type":"address"}],"name":"UnlockCallFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addLockManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_approved","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_keyOwner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"cancelAndRefund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"expirationDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"expireAndRefundFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"extend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"freeTrialLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gasRefundValue","outputs":[{"internalType":"uint256","name":"_refundValue","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"getCancelAndRefundValue","outputs":[{"internalType":"uint256","name":"refund","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_keyOwner","type":"address"}],"name":"getHasValidKey","outputs":[{"internalType":"bool","name":"isValid","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_time","type":"uint256"}],"name":"getTransferFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_duration","type":"uint256"}],"name":"grantKeyExtension","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_recipients","type":"address[]"},{"internalType":"uint256[]","name":"_expirationTimestamps","type":"uint256[]"},{"internalType":"address[]","name":"_keyManagers","type":"address[]"}],"name":"grantKeys","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"_lockCreator","type":"address"},{"internalType":"uint256","name":"_expirationDuration","type":"uint256"},{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_keyPrice","type":"uint256"},{"internalType":"uint256","name":"_maxNumberOfKeys","type":"uint256"},{"internalType":"string","name":"_lockName","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isLockManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"isRenewable","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"isValidKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"keyExpirationTimestampFor","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"keyManagerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"keyPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"lendKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxKeysPerAddress","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxNumberOfKeys","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenIdFrom","type":"uint256"},{"internalType":"uint256","name":"_tokenIdTo","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mergeKeys","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"","type":"bytes"}],"name":"migrate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"numberOfOwners","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onKeyCancelHook","outputs":[{"internalType":"contract ILockKeyCancelHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onKeyExtendHook","outputs":[{"internalType":"contract ILockKeyExtendHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onKeyGrantHook","outputs":[{"internalType":"contract ILockKeyGrantHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onKeyPurchaseHook","outputs":[{"internalType":"contract ILockKeyPurchaseHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onKeyTransferHook","outputs":[{"internalType":"contract ILockKeyTransferHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onTokenURIHook","outputs":[{"internalType":"contract ILockTokenURIHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"onValidKeyHook","outputs":[{"internalType":"contract ILockValidKeyHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicLockVersion","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_values","type":"uint256[]"},{"internalType":"address[]","name":"_recipients","type":"address[]"},{"internalType":"address[]","name":"_referrers","type":"address[]"},{"internalType":"address[]","name":"_keyManagers","type":"address[]"},{"internalType":"bytes[]","name":"_data","type":"bytes[]"}],"name":"purchase","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"purchasePriceFor","outputs":[{"internalType":"uint256","name":"minKeyPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"referrerFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"refundPenaltyBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"renewMembershipFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceLockManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"schemaVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"bool","name":"_approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_onKeyPurchaseHook","type":"address"},{"internalType":"address","name":"_onKeyCancelHook","type":"address"},{"internalType":"address","name":"_onValidKeyHook","type":"address"},{"internalType":"address","name":"_onTokenURIHook","type":"address"},{"internalType":"address","name":"_onKeyTransferHook","type":"address"},{"internalType":"address","name":"_onKeyExtendHook","type":"address"},{"internalType":"address","name":"_onKeyGrantHook","type":"address"}],"name":"setEventHooks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_refundValue","type":"uint256"}],"name":"setGasRefundValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"address","name":"_keyManager","type":"address"}],"name":"setKeyManagerOf","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_lockName","type":"string"},{"internalType":"string","name":"_lockSymbol","type":"string"},{"internalType":"string","name":"_baseTokenURI","type":"string"}],"name":"setLockMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"setOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_referrer","type":"address"},{"internalType":"uint256","name":"_feeBasisPoint","type":"uint256"}],"name":"setReferrerFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_tokenIdFrom","type":"uint256"},{"internalType":"uint256","name":"_timeShared","type":"uint256"}],"name":"shareKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_keyOwner","type":"address"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"tokenOfOwnerByIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_keyOwner","type":"address"}],"name":"totalKeys","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"_totalKeysCreated","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transferFeeBasisPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"unlendKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockProtocol","outputs":[{"internalType":"contract IUnlock","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_keyPrice","type":"uint256"},{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"updateKeyPricing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newExpirationDuration","type":"uint256"},{"internalType":"uint256","name":"_maxNumberOfKeys","type":"uint256"},{"internalType":"uint256","name":"_maxKeysPerAcccount","type":"uint256"}],"name":"updateLockConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_freeTrialLength","type":"uint256"},{"internalType":"uint256","name":"_refundPenaltyBasisPoints","type":"uint256"}],"name":"updateRefundPenalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateSchemaVersion","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_transferFeeBasisPoints","type":"uint256"}],"name":"updateTransferFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address payable","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/scripts/unlock-admin/abis/Unlock.json b/scripts/unlock-admin/abis/Unlock.json new file mode 100644 index 00000000..04d71ad0 --- /dev/null +++ b/scripts/unlock-admin/abis/Unlock.json @@ -0,0 +1 @@ +[{"inputs":[],"name":"Unlock__ALREADY_DEPLOYED","type":"error"},{"inputs":[],"name":"Unlock__INVALID_AMOUNT","type":"error"},{"inputs":[],"name":"Unlock__MANAGER_ONLY","type":"error"},{"inputs":[{"internalType":"address","name":"lockAddress","type":"address"}],"name":"Unlock__MISSING_LOCK","type":"error"},{"inputs":[],"name":"Unlock__MISSING_LOCK_TEMPLATE","type":"error"},{"inputs":[],"name":"Unlock__MISSING_PROXY_ADMIN","type":"error"},{"inputs":[],"name":"Unlock__MISSING_TEMPLATE","type":"error"},{"inputs":[],"name":"Unlock__VERSION_TOO_HIGH","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"udt","type":"address"},{"indexed":false,"internalType":"address","name":"weth","type":"address"},{"indexed":false,"internalType":"uint256","name":"estimatedGasForPurchase","type":"uint256"},{"indexed":false,"internalType":"string","name":"globalTokenSymbol","type":"string"},{"indexed":false,"internalType":"string","name":"globalTokenURI","type":"string"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"ConfigUnlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"grossNetworkProduct","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"_valueInETH","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"address","name":"lockAddress","type":"address"}],"name":"GNPChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lockAddress","type":"address"},{"indexed":false,"internalType":"uint16","name":"version","type":"uint16"}],"name":"LockUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lockOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newLockAddress","type":"address"}],"name":"NewLock","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":false,"internalType":"uint256","name":"grossNetworkProduct","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalDiscountGranted","type":"uint256"}],"name":"ResetTrackedValue","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"publicLockAddress","type":"address"}],"name":"SetLockTemplate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"impl","type":"address"},{"indexed":true,"internalType":"uint16","name":"version","type":"uint16"}],"name":"UnlockTemplateAdded","type":"event"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"__initializeOwnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"impl","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"}],"name":"addLockTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"computeAvailableDiscountFor","outputs":[{"internalType":"uint256","name":"discount","type":"uint256"},{"internalType":"uint256","name":"tokens","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_udt","type":"address"},{"internalType":"address","name":"_weth","type":"address"},{"internalType":"uint256","name":"_estimatedGasForPurchase","type":"uint256"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"string","name":"_URI","type":"string"},{"internalType":"uint256","name":"_chainId","type":"uint256"}],"name":"configUnlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_expirationDuration","type":"uint256"},{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_keyPrice","type":"uint256"},{"internalType":"uint256","name":"_maxNumberOfKeys","type":"uint256"},{"internalType":"string","name":"_lockName","type":"string"},{"internalType":"bytes12","name":"","type":"bytes12"}],"name":"createLock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"createUpgradeableLock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint16","name":"_lockVersion","type":"uint16"}],"name":"createUpgradeableLockAtVersion","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"estimatedGasForPurchase","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalBaseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getGlobalTokenSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalBaseTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalTokenSymbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"grossNetworkProduct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_unlockOwner","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initializeProxyAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"locks","outputs":[{"internalType":"bool","name":"deployed","type":"bool"},{"internalType":"uint256","name":"totalSales","type":"uint256"},{"internalType":"uint256","name":"yieldedDiscountTokens","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"networkBaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"postLockUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"protocolFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxyAdminAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicLockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_version","type":"uint16"}],"name":"publicLockImpls","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"publicLockLatestVersion","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_impl","type":"address"}],"name":"publicLockVersions","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"recordConsumedDiscount","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"recordKeyPurchase","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"lock","type":"address"}],"name":"removeLock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_grossNetworkProduct","type":"uint256"},{"internalType":"uint256","name":"_totalDiscountGranted","type":"uint256"}],"name":"resetTrackedValue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_publicLockAddress","type":"address"}],"name":"setLockTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"address","name":"_oracleAddress","type":"address"}],"name":"setOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_protocolFee","type":"uint256"}],"name":"setProtocolFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalDiscountGranted","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":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"udt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"uniswapOracles","outputs":[{"internalType":"contract IUniswapOracleV3","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockVersion","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address payable","name":"lockAddress","type":"address"},{"internalType":"uint16","name":"version","type":"uint16"}],"name":"upgradeLock","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}] \ No newline at end of file diff --git a/scripts/unlock-admin/call.js b/scripts/unlock-admin/call.js new file mode 100644 index 00000000..ab6a7dd8 --- /dev/null +++ b/scripts/unlock-admin/call.js @@ -0,0 +1,97 @@ +const { ethers } = require('ethers'); + +const ABI = { + unlock: require('./abis/Unlock.json'), + publicLock: require('./abis/PublicLock.json'), +}; + +const contracts = { + unlock: new ethers.utils.Interface(ABI.unlock), + publicLock: new ethers.utils.Interface(ABI.publicLock), +}; + +function createUpgradeableLockAtVersion(initArgs, version) { + const args = [initArgs.lockCreator, initArgs.expirationDuration, initArgs.tokenAddress, initArgs.keyPrice, initArgs.maxNumberOfKeys, initArgs.lockName]; + const data = contracts.publicLock.encodeFunctionData('initialize', args); + return { + func: simplify(contracts.unlock.getFunction('createUpgradeableLockAtVersion')), + inputs: [data, version], + }; +} + +function updateKeyPricing(keyPrice, tokenAddress) { + return { + func: simplify(contracts.publicLock.getFunction('updateKeyPricing')), + inputs: [keyPrice, tokenAddress], + }; +} + +function withdraw(tokenAddress, recipient, amount) { + return { + func: simplify(contracts.publicLock.getFunction('withdraw')), + inputs: [tokenAddress, recipient, amount], + }; +} + +function addLockManager(address) { + return { + func: simplify(contracts.publicLock.getFunction('addLockManager')), + inputs: [address], + }; +} + +function grantKeys(recipients, expirationTimestamps, keyManagers) { + return { + func: simplify(contracts.publicLock.getFunction('grantKeys')), + inputs: [recipients, expirationTimestamps, keyManagers], + }; +} + +function updateLockConfig(expirationDuration, maxNumberOfKeys, maxNumberOfKeysPerUser) { + return { + func: simplify(contracts.publicLock.getFunction('updateLockConfig')), + inputs: [expirationDuration, maxNumberOfKeys, maxNumberOfKeysPerUser], + }; +} + +function expireAndRefundFor(tokenId, refundAmount) { + return { + func: simplify(contracts.publicLock.getFunction('expireAndRefundFor')), + inputs: [tokenId, refundAmount], + }; +} + +function grantKeyExtension(tokenId, duration) { + return { + func: simplify(contracts.publicLock.getFunction('grantKeyExtension')), + inputs: [tokenId, duration], + }; +} + +function simplify(func) { + return { + name: func.name, + inputs: func.inputs.map((input) => { + return { name: input.name, type: input.type }; + }), + }; +} + +function getABI(contractName) { + if (contractName.startsWith('publicLock')) { + contractName = 'publicLock'; + } + return ABI[contractName]; +} + +module.exports = { + createUpgradeableLockAtVersion, + updateKeyPricing, + withdraw, + addLockManager, + grantKeys, + updateLockConfig, + expireAndRefundFor, + grantKeyExtension, + getABI, +}; diff --git a/scripts/unlock-admin/dev-batch-add-lock-manager.yml b/scripts/unlock-admin/dev-batch-add-lock-manager.yml new file mode 100644 index 00000000..e4d40c4c --- /dev/null +++ b/scripts/unlock-admin/dev-batch-add-lock-manager.yml @@ -0,0 +1,42 @@ +config: + batch: true + title: Batch Add Lock Manager + description: Batch addition of lock managers + network: mumbai + signer: + type: 'EOA' + address: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' # Haseeb's wallet + contracts: + publicLockScamDetector: '0x685b16Ad7Dc0711B6a49Bc95942228A1aD9369D7' # Scam Detector on Mumbai + publicLockSpamDetector: '0x18096Ba5c800FAAbb0d165952656C7FF1E77c059' + publicLockGeneral: '0x2B80295681D1c52df0a2D80119baf7639299F489' + publicLockRugPullDetector: '0x05871f396F005afeCA6fD52E5452c0DC78060be2' + +proposals: + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockScamDetector + type: addLockManager + args: + address: '0xCC274C75959f275c419fA921EBE392D29bF72728' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockSpamDetector + type: addLockManager + args: + address: '0xCC274C75959f275c419fA921EBE392D29bF72728' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockGeneral + type: addLockManager + args: + address: '0xCC274C75959f275c419fA921EBE392D29bF72728' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockRugPullDetector + type: addLockManager + args: + address: '0xCC274C75959f275c419fA921EBE392D29bF72728' diff --git a/scripts/unlock-admin/dev-batch-deploy-feeds.yml b/scripts/unlock-admin/dev-batch-deploy-feeds.yml new file mode 100644 index 00000000..94c4acde --- /dev/null +++ b/scripts/unlock-admin/dev-batch-deploy-feeds.yml @@ -0,0 +1,63 @@ +config: + batch: true + title: Deploy Unlock Feed Contracts + description: Batch deployment of Unlock feed contracts + network: mumbai + signer: + type: 'EOA' + address: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' # Haseeb's wallet + contracts: + unlock: '0x1FF7e338d5E582138C46044dc238543Ce555C963' # main Unlock contract on Mumbai + +proposals: + - title: Deploy Scam Detector Feed + description: Deploy the Unlock contract that represents membership to the Scam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Scam Detector' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x0fa8781a83e46826621b3bc094ea2a0212e71b23' # USDC token on Mumbai + keyPrice: '10000' # 0.01 USDC + expirationDuration: '86400' # 1 day in seconds + + - title: Deploy Spam Detector Feed + description: Deploy the Unlock contract that represents membership to the Spam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Spam Detector' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x0fa8781a83e46826621b3bc094ea2a0212e71b23' # USDC token on Mumbai + keyPrice: '5000' # 0.005 USDC + expirationDuration: '86400' # 1 day in seconds + + - title: Deploy Rug Pull Detector Feed + description: Deploy the Unlock contract that represents membership to the Rug Pull Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Rug Pull Detector' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x0fa8781a83e46826621b3bc094ea2a0212e71b23' # USDC token on Mumbai + keyPrice: '10000' # 0.01 USDC + expirationDuration: '172800' # 2 days in seconds + + - title: Deploy General Data Feed + description: Deploy the Unlock contract that represents membership to the General Data feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'General Data' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x107Ac13567b1b5D84691f890A5bA07EdaE1a11c3' # FORT token on Mumbai + keyPrice: '10000000000000000' # 0.01 FORT + expirationDuration: '86400' # 1 day in seconds diff --git a/scripts/unlock-admin/dev-batch-deploy-free-trial-feeds.yml b/scripts/unlock-admin/dev-batch-deploy-free-trial-feeds.yml new file mode 100644 index 00000000..6e4d3d78 --- /dev/null +++ b/scripts/unlock-admin/dev-batch-deploy-free-trial-feeds.yml @@ -0,0 +1,63 @@ +config: + batch: true + title: Deploy Unlock Free Trial Feed Contracts + description: Batch deployment of Unlock free trial feed contracts + network: mumbai + signer: + type: 'EOA' + address: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' # Haseeb's wallet + contracts: + unlock: '0x1FF7e338d5E582138C46044dc238543Ce555C963' # main Unlock contract on Mumbai + +proposals: + - title: Deploy Scam Detector Free Trial Feed + description: Deploy the Unlock contract that represents membership to the Scam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Scam Detector (Free Trial)' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x0fa8781a83e46826621b3bc094ea2a0212e71b23' # USDC token on Mumbai + keyPrice: '0' + expirationDuration: '0' + + - title: Deploy Spam Detector Free Trial Feed + description: Deploy the Unlock contract that represents membership to the Spam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Spam Detector (Free Trial)' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x0fa8781a83e46826621b3bc094ea2a0212e71b23' # USDC token on Mumbai + keyPrice: '0' + expirationDuration: '0' + + - title: Deploy Rug Pull Detector Free Trial Feed + description: Deploy the Unlock contract that represents membership to the Rug Pull Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Rug Pull Detector (Free Trial)' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x0fa8781a83e46826621b3bc094ea2a0212e71b23' # USDC token on Mumbai + keyPrice: '0' + expirationDuration: '0' + + - title: Deploy General Data Free Trial Feed + description: Deploy the Unlock contract that represents membership to the General Data feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'General Data (Free Trial)' + lockCreator: '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + tokenAddress: '0x107Ac13567b1b5D84691f890A5bA07EdaE1a11c3' # FORT token on Mumbai + keyPrice: '0' + expirationDuration: '0' diff --git a/scripts/unlock-admin/dev-batch-grant-keys.yml b/scripts/unlock-admin/dev-batch-grant-keys.yml new file mode 100644 index 00000000..a6f6e07a --- /dev/null +++ b/scripts/unlock-admin/dev-batch-grant-keys.yml @@ -0,0 +1,36 @@ +config: + batch: true + title: Airdrop Keys + description: Batch airdrop of Unlock keys + network: matic + signer: + type: 'Gnosis Safe' + address: '0x00184CFFdDc79e9A031b74A90E53634B95783B45' # Haseeb/Steven test multisig + contracts: + publicLockTest: '0xbC2B60393e81B1F5399977030ba4e2165A2e213A' + publicLockTest2: '0x4e988bC6d286Db5453c125b514FF9bd70dE53b95' + +proposals: + - title: Airdrop General Plan Keys + description: Airdrop general plan keys + contract: publicLockTest + type: grantKeys + args: + recipients: + - '0x167BF1E2885af73610F32D5cc671cB5169F07e2F' + expirationTimestamps: + - '1691469178' # unix timestamp in seconds + keyManagers: + - '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + + - title: Airdrop Rug Pull Keys + description: Airdrop rug pull keys + contract: publicLockTest2 + type: grantKeys + args: + recipients: + - '0x167BF1E2885af73610F32D5cc671cB5169F07e2F' + expirationTimestamps: + - '1691469178' # unix timestamp in seconds + keyManagers: + - '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' diff --git a/scripts/unlock-admin/dev-batch-update-lock-config.yml b/scripts/unlock-admin/dev-batch-update-lock-config.yml new file mode 100644 index 00000000..1f7b5923 --- /dev/null +++ b/scripts/unlock-admin/dev-batch-update-lock-config.yml @@ -0,0 +1,20 @@ +config: + batch: true + title: Update Free Trial Feed Contracts Config + description: Batch config update of Unlock free trial feed contracts + network: matic + signer: + type: 'Gnosis Safe' + address: '0x00184CFFdDc79e9A031b74A90E53634B95783B45' # Haseeb/Steven test multisig + contracts: + publicLockTest4: '0xedCB86544ae49A72AC33C2017A9bE8A33850369D' + +proposals: + - title: Update Free Trial Feed Config + description: Update config of the free trial Unlock contract + contract: publicLockTest4 + type: updateLockConfig + args: + expirationDuration: '0' # i.e. expires immediately if purchased + maxNumberOfKeys: '0' # i.e. non-purchaseable + maxNumberOfKeysPerUser: '1' diff --git a/scripts/unlock-admin/example.yaml b/scripts/unlock-admin/example.yaml new file mode 100644 index 00000000..176d0669 --- /dev/null +++ b/scripts/unlock-admin/example.yaml @@ -0,0 +1,52 @@ +# This file shows a full example of a propose.yaml to create. + +config: + batch: false # only set to true if all proposals should be batched into one proposal + title: Deploy Unlock Feed Contracts # required if batch=true + description: Batch deployment of Unlock feed contracts # required if batch=true + network: matic # set to mumbai if testing + signer: + type: 'EOA' # set to 'Gnosis Safe' if multisig + address: '0x874B5d427b2d27F6Ea0ed3BCE4De454824AEC9cC' + contracts: + unlock: '0xE8E5cd156f89F7bdB267EabD5C43Af3d5AF2A78f' + publicLock: '0xbC2B60393e81B1F5399977030ba4e2165A2e213A' + +proposals: + - title: Deploy new PublicLock contract # not used if batch=true + description: To be used for one of the plans # not used if batch=true + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Spam Detector (FORT)' + lockCreator: '0x874B5d427b2d27F6Ea0ed3BCE4De454824AEC9cC' # this account manages the lock + tokenAddress: '0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1' # FORT token on Polygon + keyPrice: '1000000000000000000' # enter in wei: example is 1 wei + expirationDuration: '86400' # one day in seconds: expires every day + #maxNumberOfKeys: '100' # set this only if necessary: defaults to unlimited + + - title: Update key pricing + description: Using a different price for the same token + contract: publicLock + type: updateKeyPricing + args: + keyPrice: '10000000000000000000' # enter in wei: example is 10 wei + tokenAddress: '0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1' # FORT token on Polygon + + - title: Withdraw from lock + description: This is for withdrawing the total amount so far + contract: publicLock + type: withdraw + args: + tokenAddress: '0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1' # FORT token on Polygon + recipient: '0x874B5d427b2d27F6Ea0ed3BCE4De454824AEC9cC' + amount: '10000000000000000000' # enter in wei: example is 10 wei + + - title: Add lock manager + description: Adds a new address as an Unlock lock manager + contract: publicLock + type: addLockManager + args: + address: '0x874B5d427b2d27F6Ea0ed3BCE4De454824AEC9cC' diff --git a/scripts/unlock-admin/prod-batch-add-lock-manager-free-trial.yml b/scripts/unlock-admin/prod-batch-add-lock-manager-free-trial.yml new file mode 100644 index 00000000..0089a019 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-add-lock-manager-free-trial.yml @@ -0,0 +1,42 @@ +config: + batch: true + title: Add Free Trial Feeds Lock Manager + description: Batch addition of lock manager to free trial feeds + network: matic + signer: + type: 'Gnosis Safe' + address: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' # Foundation multisig + contracts: + publicLockGeneralFreeTrial: '0xB73d7Cb1bB6340adE0bB3D7A2C396EB2551aD20d' + publicLockScamDetectorFreeTrial: '0xe4610C8ac8e91978e6319fB1dd64b10d87a46450' + publicLockSpamDetectorFreeTrial: '0xf84b294E47bcfd817d7d2B7a317d99AFD01E4cc6' + publicLockRugPullDetectorFreeTrial: '0xa7FD423969e923fC7c4D2eF315C0A14361A0b1c4' + +proposals: + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockGeneralFreeTrial + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockRugPullDetectorFreeTrial + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockScamDetectorFreeTrial + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockSpamDetectorFreeTrial + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' diff --git a/scripts/unlock-admin/prod-batch-add-lock-manager.yml b/scripts/unlock-admin/prod-batch-add-lock-manager.yml new file mode 100644 index 00000000..b55d414d --- /dev/null +++ b/scripts/unlock-admin/prod-batch-add-lock-manager.yml @@ -0,0 +1,42 @@ +config: + batch: true + title: Batch Add Lock Manager + description: Batch addition of lock manager + network: matic + signer: + type: 'Gnosis Safe' + address: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' # Foundation multisig + contracts: + publicLockGeneral: '0x4E0c80548e67A6E05464E540729222EB9812444d' + publicLockRugPullDetector: '0x525d8d73f11a8586482F4f74C105D9d8B7cf73dA' + publicLockScamDetector: '0x54089510Aec879CA42e08BC4B166be8362B56BB2' + publicLockSpamDetector: '0x6453379CBC14f7a277319B6C8b7577Ae78524968' + +proposals: + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockGeneral + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockRugPullDetector + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockScamDetector + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Add Lock Manager + description: Add a lock manager + contract: publicLockSpamDetector + type: addLockManager + args: + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' diff --git a/scripts/unlock-admin/prod-batch-deploy-feeds.yml b/scripts/unlock-admin/prod-batch-deploy-feeds.yml new file mode 100644 index 00000000..a95257e0 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-deploy-feeds.yml @@ -0,0 +1,63 @@ +config: + batch: true + title: Deploy Unlock Feed Contracts + description: Batch deployment of Unlock feed contracts + network: matic + signer: + type: 'Gnosis Safe' + address: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' # Foundation multisig + contracts: + unlock: '0xE8E5cd156f89F7bdB267EabD5C43Af3d5AF2A78f' # main Unlock contract on Polygon + +proposals: + - title: Deploy Scam Detector Feed + description: Deploy the Unlock contract that represents membership to the Scam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Scam Detector' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174' # USDC token on Polygon + keyPrice: '899000000' # 899 USDC + expirationDuration: '2635200' # 30.5 days in seconds + + - title: Deploy Spam Detector Feed + description: Deploy the Unlock contract that represents membership to the Spam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Spam Detector' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174' # USDC token on Polygon + keyPrice: '49000000' # 49 USDC + expirationDuration: '2635200' # 30.5 days in seconds + + - title: Deploy Rug Pull Detector Feed + description: Deploy the Unlock contract that represents membership to the Rug Pull Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Rug Pull Detector' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174' # USDC token on Polygon + keyPrice: '899000000' # 899 USDC + expirationDuration: '2635200' # 30.5 days in seconds + + - title: Deploy General Data Feed + description: Deploy the Unlock contract that represents membership to the General Data feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'General Data' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1' # FORT token on Polygon + keyPrice: '250000000000000000000' # 250 FORT + expirationDuration: '2635200' # 30.5 days in seconds diff --git a/scripts/unlock-admin/prod-batch-deploy-free-trial-feeds.yml b/scripts/unlock-admin/prod-batch-deploy-free-trial-feeds.yml new file mode 100644 index 00000000..7c723f0c --- /dev/null +++ b/scripts/unlock-admin/prod-batch-deploy-free-trial-feeds.yml @@ -0,0 +1,63 @@ +config: + batch: true + title: Deploy Unlock Free Trial Feed Contracts + description: Batch deployment of Unlock free trial feed contracts + network: matic + signer: + type: 'Gnosis Safe' + address: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' # Foundation multisig + contracts: + unlock: '0xE8E5cd156f89F7bdB267EabD5C43Af3d5AF2A78f' # main Unlock contract on Polygon + +proposals: + - title: Deploy Scam Detector Free Trial Feed + description: Deploy the Unlock contract that represents membership to the Scam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Scam Detector (Free Trial)' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174' # USDC token on Polygon + keyPrice: '0' + expirationDuration: '0' + + - title: Deploy Spam Detector Free Trial Feed + description: Deploy the Unlock contract that represents membership to the Spam Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Spam Detector (Free Trial)' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174' # USDC token on Polygon + keyPrice: '0' + expirationDuration: '0' + + - title: Deploy Rug Pull Detector Free Trial Feed + description: Deploy the Unlock contract that represents membership to the Rug Pull Detector feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'Rug Pull Detector (Free Trial)' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x2791bca1f2de4661ed88a30c99a7a9449aa84174' # USDC token on Polygon + keyPrice: '0' + expirationDuration: '0' + + - title: Deploy General Data Free Trial Feed + description: Deploy the Unlock contract that represents membership to the General Data feed + contract: unlock + type: deploy + args: + version: '13' + initArgs: + lockName: 'General Data (Free Trial)' + lockCreator: '0x30ceaeC1d8Ed347B91d45077721c309242db3D6d' + tokenAddress: '0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1' # FORT token on Polygon + keyPrice: '0' + expirationDuration: '0' diff --git a/scripts/unlock-admin/prod-batch-expire-general-plan-keys.yml b/scripts/unlock-admin/prod-batch-expire-general-plan-keys.yml new file mode 100644 index 00000000..d7fefe16 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-expire-general-plan-keys.yml @@ -0,0 +1,257 @@ +config: + batch: true + title: Expire Airdropped General Plan Keys + description: Batch expiry of airdropped General Plan Unlock keys + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneral: '0x4E0c80548e67A6E05464E540729222EB9812444d' + +proposals: + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '3' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '4' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '5' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '6' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '7' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '8' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '9' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '10' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '11' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '12' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '13' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '14' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '15' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '16' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '17' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '18' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '19' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '20' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '21' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '22' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '23' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '24' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '25' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '26' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '27' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '28' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '29' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '30' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '31' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '32' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '33' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '34' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '35' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '36' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '37' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '38' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '39' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '40' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '41' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '42' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '43' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '44' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '45' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '46' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '47' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '48' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '49' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '50' + refundAmount: '0' + - contract: publicLockGeneral + type: expireAndRefundFor + args: + tokenId: '53' + refundAmount: '0' diff --git a/scripts/unlock-admin/prod-batch-expire-scam-detector-keys.yml b/scripts/unlock-admin/prod-batch-expire-scam-detector-keys.yml new file mode 100644 index 00000000..cc5645c0 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-expire-scam-detector-keys.yml @@ -0,0 +1,172 @@ +config: + batch: true + title: Expire Airdropped Scam Detector Keys + description: Batch expiry of airdropped Scam Detector Unlock keys + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockScamDetector: '0x54089510Aec879CA42e08BC4B166be8362B56BB2' + +proposals: + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '1' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '2' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '3' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '4' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '5' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '6' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '7' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '8' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '9' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '10' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '11' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '12' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '13' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '14' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '15' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '16' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '17' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '18' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '19' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '20' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '21' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '22' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '23' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '24' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '25' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '26' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '27' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '28' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '29' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '30' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '31' + refundAmount: '0' + - contract: publicLockScamDetector + type: expireAndRefundFor + args: + tokenId: '32' + refundAmount: '0' diff --git a/scripts/unlock-admin/prod-batch-grant-free-trial.yml b/scripts/unlock-admin/prod-batch-grant-free-trial.yml new file mode 100644 index 00000000..bb6d1392 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-grant-free-trial.yml @@ -0,0 +1,192 @@ +config: + batch: true + title: Batch Airdrop Keys + description: Batch airdrop of Unlock keys + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneralFreeTrial: '0xB73d7Cb1bB6340adE0bB3D7A2C396EB2551aD20d' + publicLockScamDetectorFreeTrial: '0xe4610C8ac8e91978e6319fB1dd64b10d87a46450' + +proposals: + - title: Airdrop General Plan 15-day Keys (18) + description: Airdrop general plan 15-day keys + contract: publicLockGeneralFreeTrial + type: grantKeys + args: + recipients: + - '0x6aea36C4a9Cf8AC053c07E662fa27e8BDF047121' + - '0xE34dC9DB5F87f1854F687D94FF37db6993ef1441' + - '0x51c9e0D122102b7babB647b294CB63DC6af9216E' + - '0x9C8ED6c23c26dECE8484D56617f807A32636Df00' + - '0x81813Bd41459c0Bb757308C855c0521A4e308E36' + - '0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8' + - '0x237C643De19453d2EBEC41a77F4dbf1Db2b67fb0' + - '0x5354012663b2e0859e89125AeA2E8317e57f48cc' + - '0xaCfE4511CE883C14c4eA40563F176C3C09b4c47C' + - '0x9B5715C99d3A9db84cAA904f9f442220651436e8' + - '0x02fD3818115955be87a19f83e2568Ca840b93FD3' + - '0x7A3556E10A621124a0749F73C481D13ec3A446C6' + - '0x421af9aBC87197A917b87f8d2b2D8B0213D47Dbe' + - '0xBA35D683D382232488934672CfB9aa19214E228F' + - '0x94587a95917188B338C822de2D1e77074131589f' + - '0xD03ee5F22C5d46f502fbc42d39354d46540627B0' + - '0xb892736038e21B6F4906BD0cC3CfDeC1bc275cb7' + - '0xe8Bed3ee8c8B459156aa45BA5ceFF7f3Ac728c3B' + expirationTimestamps: + - '1692835200' # 15 days from Aug 8 2023 unix timestamp in seconds + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop General Plan 30-day Keys (6) + description: Airdrop general plan 30-day keys + contract: publicLockGeneralFreeTrial + type: grantKeys + args: + recipients: + - '0x5C07cbbD3F74925A362acAB166e9b1C59a5235c3' + - '0xe62E022C9dc91CB5F19F0d92F3537C2C69F74b63' + - '0xB98dF1e105509aD6F4e40D3AC25989CD591679a5' + - '0x22f318a46e02245e7aDb6B6FDd0ce5C3d4330430' + - '0xdd7f5c72C7D24Aae2ddAE28cdce45A1F2469699d' + - '0xe3eFcCF966921Ad291fdC31Fa57F9044F105bc98' + expirationTimestamps: + - '1694217600' # 30 days from Aug 8 2023 unix timestamp in seconds + - '1694217600' + - '1694217600' + - '1694217600' + - '1694217600' + - '1694217600' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop Scam Detector Plan 30-day Keys (5) + description: Airdrop scam detector plan 30-day keys + contract: publicLockScamDetectorFreeTrial + type: grantKeys + args: + recipients: + - '0x5C07cbbD3F74925A362acAB166e9b1C59a5235c3' + - '0xe62E022C9dc91CB5F19F0d92F3537C2C69F74b63' + - '0xB98dF1e105509aD6F4e40D3AC25989CD591679a5' + - '0x22f318a46e02245e7aDb6B6FDd0ce5C3d4330430' + - '0xe3eFcCF966921Ad291fdC31Fa57F9044F105bc98' + expirationTimestamps: + - '1694217600' # 30 days from Aug 8 2023 unix timestamp in seconds + - '1694217600' + - '1694217600' + - '1694217600' + - '1694217600' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop General Plan Unlimited Keys + description: Airdrop general plan unlimited keys + contract: publicLockGeneralFreeTrial + type: grantKeys + args: + recipients: + - '0xad7547d09015664943d0A7c1BeA47f28dF298EC0' + - '0x466CF86417dd89f5800C64708C407Bda836E5E78' + - '0x5075534aFB4b73CbB6744eA8B59d78Ca56059471' + - '0xc1b7551c3A01975bbde527f29f7C37566746f0EA' + - '0x88dC3a2284FA62e0027d6D6B1fCfDd2141a143b8' + - '0x061f191f9a60B3373D3146b1F153c03Ec2C2A05E' + - '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + - '0x7959f8E09D7740c9bd5f828133EbFcc902F8DD6b' + - '0xD65fe9Db69044F97609AFF0810F9C86652DB6452' + - '0xebFb85430E23A8593dDB24fE52D9aBD67D357C95' + - '0xf77dcB7dbA19d2685bFC51A6eE5c9Cf4f2346E77' + - '0x4E2DaaE4725088BF9e21Cf3D4CADfa528a870728' + - '0x5006FC70e5E99ACfAd31e3023F0be31d749482ab' + - '0x11F6955BC1143920beA9B4c7ff5c27F01F2675ef' + - '0x17B45F59dD4F30A5b9FB87f6054e5a885ff6fde5' + - '0xb53411097807e19Ab74EF19197B0c0115a8CA081' + - '0xab67B1ebe05791127811AC73B3BbF58e53C8D675' + - '0x712c88aa093de1d131b41CE4171456b16Acc379a' + - '0x906E567A48aA192AC8a95cb09dA4c70984588F81' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' diff --git a/scripts/unlock-admin/prod-batch-grant-free-trial2.yml b/scripts/unlock-admin/prod-batch-grant-free-trial2.yml new file mode 100644 index 00000000..7a3df7f7 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-grant-free-trial2.yml @@ -0,0 +1,165 @@ +config: + batch: true + title: Batch Airdrop Keys 2 + description: Batch airdrop of Unlock keys 2 + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneralFreeTrial: '0xB73d7Cb1bB6340adE0bB3D7A2C396EB2551aD20d' + publicLockScamDetectorFreeTrial: '0xe4610C8ac8e91978e6319fB1dd64b10d87a46450' + +proposals: + - title: Airdrop General Plan Unlimited Keys (14) + description: Airdrop general plan unlimited keys + contract: publicLockGeneralFreeTrial + type: grantKeys + args: + recipients: + - '0x6Db5Ad6af0142E33179ee51D5704Fa362Ca0cA56' + - '0xDCc157C34dB2a6b5E028D7d4503393CB87913251' + - '0x6C9b1856617fE451C74806e6606d0D9E43b268F7' + - '0xE475A44a55df395BF37384c6FCC76D0C9628AC72' + - '0xa13d0b033A11AcC07726F080999F0c3E77C3906B' + - '0xA2f25b276E0dE4e6443215B47432F9416231FC06' + - '0xcDd46C5d0140010D5F2eDc8B5616FE79ab960Fe7' + - '0x4Ba070120E234A69D8B5B7C0EEB020eaFF133fCB' + - '0x49768626321aF7470A14Bb098F2934935250311D' + - '0xd4a9c31541a3b296868EA8BDaB63D358e3aB3b5E' + - '0x6077a8D9AE6f6af7E8527aB0091a6520Bb1Bc5fd' + - '0x78ffc312C28C90cf2e05798AE5b9B97464072A79' + - '0xd1721142367c2DbbCBa95E81244E51C5029b4A5A' + - '0x183d13c4fcb5133ea52345a9037c9c25a5aa139d' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop Scam Detector Plan Unlimited Keys (31) + description: Airdrop scam detector plan unlimited keys + contract: publicLockScamDetectorFreeTrial + type: grantKeys + args: + recipients: + - '0xad7547d09015664943d0A7c1BeA47f28dF298EC0' + - '0x466CF86417dd89f5800C64708C407Bda836E5E78' + - '0xc1b7551c3A01975bbde527f29f7C37566746f0EA' + - '0x88dC3a2284FA62e0027d6D6B1fCfDd2141a143b8' + - '0x061f191f9a60B3373D3146b1F153c03Ec2C2A05E' + - '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + - '0x7959f8E09D7740c9bd5f828133EbFcc902F8DD6b' + - '0xD65fe9Db69044F97609AFF0810F9C86652DB6452' + - '0xebFb85430E23A8593dDB24fE52D9aBD67D357C95' + - '0xf77dcB7dbA19d2685bFC51A6eE5c9Cf4f2346E77' + - '0x4E2DaaE4725088BF9e21Cf3D4CADfa528a870728' + - '0x5006FC70e5E99ACfAd31e3023F0be31d749482ab' + - '0x11F6955BC1143920beA9B4c7ff5c27F01F2675ef' + - '0x17B45F59dD4F30A5b9FB87f6054e5a885ff6fde5' + - '0xb53411097807e19Ab74EF19197B0c0115a8CA081' + - '0xab67B1ebe05791127811AC73B3BbF58e53C8D675' + - '0x712c88aa093de1d131b41CE4171456b16Acc379a' + - '0x906E567A48aA192AC8a95cb09dA4c70984588F81' + - '0x6Db5Ad6af0142E33179ee51D5704Fa362Ca0cA56' + - '0xDCc157C34dB2a6b5E028D7d4503393CB87913251' + - '0x6C9b1856617fE451C74806e6606d0D9E43b268F7' + - '0xE475A44a55df395BF37384c6FCC76D0C9628AC72' + - '0xa13d0b033A11AcC07726F080999F0c3E77C3906B' + - '0xA2f25b276E0dE4e6443215B47432F9416231FC06' + - '0xcDd46C5d0140010D5F2eDc8B5616FE79ab960Fe7' + - '0x4Ba070120E234A69D8B5B7C0EEB020eaFF133fCB' + - '0x49768626321aF7470A14Bb098F2934935250311D' + - '0xd4a9c31541a3b296868EA8BDaB63D358e3aB3b5E' + - '0x6077a8D9AE6f6af7E8527aB0091a6520Bb1Bc5fd' + - '0x78ffc312C28C90cf2e05798AE5b9B97464072A79' + - '0xd1721142367c2DbbCBa95E81244E51C5029b4A5A' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' diff --git a/scripts/unlock-admin/prod-batch-grant-keys.yml b/scripts/unlock-admin/prod-batch-grant-keys.yml new file mode 100644 index 00000000..af5c8de3 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-grant-keys.yml @@ -0,0 +1,156 @@ +config: + batch: true + title: Airdrop Keys + description: Batch airdrop of Unlock keys + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneral: '0x4E0c80548e67A6E05464E540729222EB9812444d' + publicLockScamDetector: '0x54089510Aec879CA42e08BC4B166be8362B56BB2' + +proposals: + - title: Airdrop General Plan 15-day Keys + description: Airdrop general plan 15-day keys + contract: publicLockGeneral + type: grantKeys + args: + recipients: + - '0x6aea36C4a9Cf8AC053c07E662fa27e8BDF047121' + - '0xE34dC9DB5F87f1854F687D94FF37db6993ef1441' + - '0x51c9e0D122102b7babB647b294CB63DC6af9216E' + - '0x9C8ED6c23c26dECE8484D56617f807A32636Df00' + - '0x81813Bd41459c0Bb757308C855c0521A4e308E36' + - '0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8' + - '0x237C643De19453d2EBEC41a77F4dbf1Db2b67fb0' + - '0x5354012663b2e0859e89125AeA2E8317e57f48cc' + - '0xaCfE4511CE883C14c4eA40563F176C3C09b4c47C' + - '0x9B5715C99d3A9db84cAA904f9f442220651436e8' + - '0x02fD3818115955be87a19f83e2568Ca840b93FD3' + - '0x7A3556E10A621124a0749F73C481D13ec3A446C6' + - '0x421af9aBC87197A917b87f8d2b2D8B0213D47Dbe' + expirationTimestamps: + - '1692835200' # 15 days from Aug 8 2023 unix timestamp in seconds + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + - '1692835200' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop General Plan 30-day Keys + description: Airdrop general plan 30-day keys + contract: publicLockGeneral + type: grantKeys + args: + recipients: + - '0x5C07cbbD3F74925A362acAB166e9b1C59a5235c3' + - '0xe62E022C9dc91CB5F19F0d92F3537C2C69F74b63' + - '0xB98dF1e105509aD6F4e40D3AC25989CD591679a5' + - '0x22f318a46e02245e7aDb6B6FDd0ce5C3d4330430' + expirationTimestamps: + - '1694217600' # 30 days from Aug 8 2023 unix timestamp in seconds + - '1694217600' + - '1694217600' + - '1694217600' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop Scam Detector Plan 30-day Keys + description: Airdrop scam detector plan 30-day keys + contract: publicLockScamDetector + type: grantKeys + args: + recipients: + - '0x5C07cbbD3F74925A362acAB166e9b1C59a5235c3' + - '0xe62E022C9dc91CB5F19F0d92F3537C2C69F74b63' + - '0xB98dF1e105509aD6F4e40D3AC25989CD591679a5' + - '0x22f318a46e02245e7aDb6B6FDd0ce5C3d4330430' + expirationTimestamps: + - '1694217600' # 30 days from Aug 8 2023 unix timestamp in seconds + - '1694217600' + - '1694217600' + - '1694217600' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop General Plan Unlimited Keys + description: Airdrop general plan unlimited keys + contract: publicLockGeneral + type: grantKeys + args: + recipients: + - '0xad7547d09015664943d0A7c1BeA47f28dF298EC0' + - '0x466CF86417dd89f5800C64708C407Bda836E5E78' + - '0x5075534aFB4b73CbB6744eA8B59d78Ca56059471' + - '0xc1b7551c3A01975bbde527f29f7C37566746f0EA' + - '0x88dC3a2284FA62e0027d6D6B1fCfDd2141a143b8' + - '0x061f191f9a60B3373D3146b1F153c03Ec2C2A05E' + - '0x577022b59D1C25323ab524Fe78d2F6347b5C69f0' + - '0x7959f8E09D7740c9bd5f828133EbFcc902F8DD6b' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop Scam Detector Plan Unlimited Keys + description: Airdrop scam detector plan unlimited keys + contract: publicLockScamDetector + type: grantKeys + args: + recipients: + - '0xad7547d09015664943d0A7c1BeA47f28dF298EC0' + - '0x466CF86417dd89f5800C64708C407Bda836E5E78' + - '0xc1b7551c3A01975bbde527f29f7C37566746f0EA' + - '0x88dC3a2284FA62e0027d6D6B1fCfDd2141a143b8' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + - '33248440764' + - '33248440764' + - '33248440764' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' diff --git a/scripts/unlock-admin/prod-batch-grant-keys2.yml b/scripts/unlock-admin/prod-batch-grant-keys2.yml new file mode 100644 index 00000000..5909c1e3 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-grant-keys2.yml @@ -0,0 +1,171 @@ +config: + batch: true + title: Airdrop Keys + description: Batch airdrop of Unlock keys + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneral: '0x4E0c80548e67A6E05464E540729222EB9812444d' + publicLockScamDetector: '0x54089510Aec879CA42e08BC4B166be8362B56BB2' + +proposals: + - title: Airdrop General Plan Unlimited Keys + description: Airdrop general plan unlimited keys + contract: publicLockGeneral + type: grantKeys + args: + recipients: + - '0xebFb85430E23A8593dDB24fE52D9aBD67D357C95' + - '0xf77dcB7dbA19d2685bFC51A6eE5c9Cf4f2346E77' + - '0x4E2DaaE4725088BF9e21Cf3D4CADfa528a870728' + - '0x5006FC70e5E99ACfAd31e3023F0be31d749482ab' + - '0x11F6955BC1143920beA9B4c7ff5c27F01F2675ef' + - '0x17B45F59dD4F30A5b9FB87f6054e5a885ff6fde5' + - '0xb53411097807e19Ab74EF19197B0c0115a8CA081' + - '0xab67B1ebe05791127811AC73B3BbF58e53C8D675' + - '0x712c88aa093de1d131b41CE4171456b16Acc379a' + - '0x906E567A48aA192AC8a95cb09dA4c70984588F81' + - '0x6Db5Ad6af0142E33179ee51D5704Fa362Ca0cA56' + - '0xDCc157C34dB2a6b5E028D7d4503393CB87913251' + - '0x6C9b1856617fE451C74806e6606d0D9E43b268F7' + - '0xE475A44a55df395BF37384c6FCC76D0C9628AC72' + - '0xa13d0b033A11AcC07726F080999F0c3E77C3906B' + - '0xA2f25b276E0dE4e6443215B47432F9416231FC06' + - '0xcDd46C5d0140010D5F2eDc8B5616FE79ab960Fe7' + - '0x4Ba070120E234A69D8B5B7C0EEB020eaFF133fCB' + - '0x49768626321aF7470A14Bb098F2934935250311D' + - '0xd4a9c31541a3b296868EA8BDaB63D358e3aB3b5E' + - '0x6077a8D9AE6f6af7E8527aB0091a6520Bb1Bc5fd' + - '0x78ffc312C28C90cf2e05798AE5b9B97464072A79' + - '0xd1721142367c2DbbCBa95E81244E51C5029b4A5A' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + + - title: Airdrop Scam Detector Plan Unlimited Keys + description: Airdrop scam detector plan unlimited keys + contract: publicLockScamDetector + type: grantKeys + args: + recipients: + - '0xD65fe9Db69044F97609AFF0810F9C86652DB6452' + - '0xebFb85430E23A8593dDB24fE52D9aBD67D357C95' + - '0xf77dcB7dbA19d2685bFC51A6eE5c9Cf4f2346E77' + - '0x4E2DaaE4725088BF9e21Cf3D4CADfa528a870728' + - '0x5006FC70e5E99ACfAd31e3023F0be31d749482ab' + - '0x11F6955BC1143920beA9B4c7ff5c27F01F2675ef' + - '0x17B45F59dD4F30A5b9FB87f6054e5a885ff6fde5' + - '0xb53411097807e19Ab74EF19197B0c0115a8CA081' + - '0xab67B1ebe05791127811AC73B3BbF58e53C8D675' + - '0x712c88aa093de1d131b41CE4171456b16Acc379a' + - '0x906E567A48aA192AC8a95cb09dA4c70984588F81' + - '0x6Db5Ad6af0142E33179ee51D5704Fa362Ca0cA56' + - '0xDCc157C34dB2a6b5E028D7d4503393CB87913251' + - '0x6C9b1856617fE451C74806e6606d0D9E43b268F7' + - '0xE475A44a55df395BF37384c6FCC76D0C9628AC72' + - '0xa13d0b033A11AcC07726F080999F0c3E77C3906B' + - '0xA2f25b276E0dE4e6443215B47432F9416231FC06' + - '0xcDd46C5d0140010D5F2eDc8B5616FE79ab960Fe7' + - '0x4Ba070120E234A69D8B5B7C0EEB020eaFF133fCB' + - '0x49768626321aF7470A14Bb098F2934935250311D' + - '0xd4a9c31541a3b296868EA8BDaB63D358e3aB3b5E' + - '0x6077a8D9AE6f6af7E8527aB0091a6520Bb1Bc5fd' + - '0x78ffc312C28C90cf2e05798AE5b9B97464072A79' + - '0xd1721142367c2DbbCBa95E81244E51C5029b4A5A' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + - '33248440764' + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' diff --git a/scripts/unlock-admin/prod-batch-grant-keys3.yml b/scripts/unlock-admin/prod-batch-grant-keys3.yml new file mode 100644 index 00000000..4b381186 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-grant-keys3.yml @@ -0,0 +1,23 @@ +config: + batch: true + title: Airdrop Keys + description: Batch airdrop of Unlock keys + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneral: '0x4E0c80548e67A6E05464E540729222EB9812444d' + +proposals: + - title: Airdrop General Plan Unlimited Keys + description: Airdrop general plan unlimited keys + contract: publicLockGeneral + type: grantKeys + args: + recipients: + - '0x183d13c4fCb5133EA52345A9037C9c25A5Aa139D' + expirationTimestamps: + - '33248440764' # 1000 years from Aug 8 2023 unix timestamp in seconds + keyManagers: + - '0x5854E0AbCec28EDead274FEF0ec6516087052E99' diff --git a/scripts/unlock-admin/prod-batch-update-lock-config.yml b/scripts/unlock-admin/prod-batch-update-lock-config.yml new file mode 100644 index 00000000..0142f9e0 --- /dev/null +++ b/scripts/unlock-admin/prod-batch-update-lock-config.yml @@ -0,0 +1,50 @@ +config: + batch: true + title: Update Free Trial Feeds Config + description: Batch config update of Unlock free trial contracts + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneralFreeTrial: '0xB73d7Cb1bB6340adE0bB3D7A2C396EB2551aD20d' + publicLockScamDetectorFreeTrial: '0xe4610C8ac8e91978e6319fB1dd64b10d87a46450' + publicLockSpamDetectorFreeTrial: '0xf84b294E47bcfd817d7d2B7a317d99AFD01E4cc6' + publicLockRugPullDetectorFreeTrial: '0xa7FD423969e923fC7c4D2eF315C0A14361A0b1c4' + +proposals: + - title: Update General Plan Free Trial Config + description: Update config of the General Plan free trial contract + contract: publicLockGeneralFreeTrial + type: updateLockConfig + args: + expirationDuration: '0' # i.e. expires immediately (if purchased) + maxNumberOfKeys: '0' # i.e. non-purchaseable + maxNumberOfKeysPerUser: '1' + + - title: Update Scam Detector Free Trial Config + description: Update config of the Scam Detector free trial contract + contract: publicLockScamDetectorFreeTrial + type: updateLockConfig + args: + expirationDuration: '0' # i.e. expires immediately (if purchased) + maxNumberOfKeys: '0' # i.e. non-purchaseable + maxNumberOfKeysPerUser: '1' + + - title: Update Spam Detector Free Trial Config + description: Update config of the Spam Detector free trial contract + contract: publicLockSpamDetectorFreeTrial + type: updateLockConfig + args: + expirationDuration: '0' # i.e. expires immediately (if purchased) + maxNumberOfKeys: '0' # i.e. non-purchaseable + maxNumberOfKeysPerUser: '1' + + - title: Update Rug Pull Detector Free Trial Config + description: Update config of the Rug Pull Detector free trial contract + contract: publicLockRugPullDetectorFreeTrial + type: updateLockConfig + args: + expirationDuration: '0' # i.e. expires immediately (if purchased) + maxNumberOfKeys: '0' # i.e. non-purchaseable + maxNumberOfKeysPerUser: '1' diff --git a/scripts/unlock-admin/prod-withdraw-rewards-week-08-14-2023.yml b/scripts/unlock-admin/prod-withdraw-rewards-week-08-14-2023.yml new file mode 100644 index 00000000..ca08fe4d --- /dev/null +++ b/scripts/unlock-admin/prod-withdraw-rewards-week-08-14-2023.yml @@ -0,0 +1,23 @@ +config: + batch: true + title: Withdraw Bot Rewards Week 08-14-2023 + description: Withdraw bot rewards for week 08-14-2023 + network: matic + signer: + type: 'Gnosis Safe' + address: '0x5854E0AbCec28EDead274FEF0ec6516087052E99' # Forta Fees multisig + contracts: + publicLockGeneral: '0x4E0c80548e67A6E05464E540729222EB9812444d' + # publicLockRugPullDetector: '0x525d8d73f11a8586482F4f74C105D9d8B7cf73dA' + # publicLockScamDetector: '0x54089510Aec879CA42e08BC4B166be8362B56BB2' + # publicLockSpamDetector: '0x6453379CBC14f7a277319B6C8b7577Ae78524968' + +proposals: + - title: Withdraw General Plan + description: Withdraw General Plan + contract: publicLockGeneral + type: withdraw + args: + tokenAddress: '0x9ff62d1FC52A907B6DCbA8077c2DDCA6E6a9d3e1' # FORT token on Polygon + recipient: '0x15d3c7e811582Be09Bb8673cD603Bb2F22D1e47B' # Polygon relayer + amount: '408333333330000000000' # 23.33% of 1750 FORT = 408.33 FORT diff --git a/scripts/unlock-admin/propose.js b/scripts/unlock-admin/propose.js new file mode 100644 index 00000000..1ec645a6 --- /dev/null +++ b/scripts/unlock-admin/propose.js @@ -0,0 +1,120 @@ +const fs = require('fs'); +require('dotenv').config(); +const { AdminClient } = require('defender-admin-client'); +const defenderAdmin = new AdminClient({ + apiKey: process.env.DEFENDER_API_KEY, + apiSecret: process.env.DEFENDER_SECRET_KEY, +}); +const jsyaml = require('js-yaml'); +const { ethers } = require('ethers'); + +const call = require('./call'); + +async function main() { + const proposalFile = jsyaml.load(fs.readFileSync(process.argv[2], 'utf8')); + // console.log(JSON.stringify(proposalFile)); + if (proposalFile.config.batch != true) { + // create individual proposals + for (let i = 0; i < proposalFile.proposals.length; i++) { + const proposal = proposalFile.proposals[i]; + await propose(proposalFile.config, proposal); + } + } else { + // create one batch proposal + await batchPropose(proposalFile.config, proposalFile.proposals); + } +} + +async function batchPropose(config, proposals) { + const network = config.network; + const contracts = {}; + const steps = []; + // create steps for batch proposal + for (const proposal of proposals) { + const { func, inputs } = getCall(proposal); + const contractName = proposal.contract; + const contractAddress = config.contracts[contractName]; + steps.push({ + contractId: `${network}-${contractAddress}`, + targetFunction: func, + functionInputs: inputs, + type: 'custom', + }); + contracts[contractAddress] = { + address: contractAddress, + name: contractName, + network, + abi: JSON.stringify(call.getABI(contractName)), + }; + } + // create batch proposal + const result = await defenderAdmin.createProposal({ + contract: Object.keys(contracts).map((key) => contracts[key]), + title: config.title, + description: config.description, + type: 'batch', + via: config.signer.address, + viaType: config.signer.type, + metadata: {}, // required field but empty + steps, + }); + console.log(result.url); +} + +async function propose(config, proposal) { + const { func, inputs } = getCall(proposal); + const proposalParams = { + contract: { + address: config.contracts[proposal.contract], + network: config.network, + }, + title: proposal.title, + description: proposal.description, + type: 'custom', + functionInterface: func, + functionInputs: inputs, + via: config.signer.address, + viaType: config.signer.type, + }; + const result = await defenderAdmin.createProposal(proposalParams); + console.log(`${proposal.title}: ${result.url}`); +} + +function getCall(proposal) { + const { args } = proposal; + switch (proposal.type) { + case 'deploy': + if (!args.initArgs.maxNumberOfKeys) { + args.initArgs.maxNumberOfKeys = ethers.constants.MaxUint256.toString(); + } + return call.createUpgradeableLockAtVersion(args.initArgs, args.version); + + case 'updateKeyPricing': + return call.updateKeyPricing(args.keyPrice, args.tokenAddress); + + case 'withdraw': + return call.withdraw(args.tokenAddress, args.recipient, args.amount); + + case 'addLockManager': + return call.addLockManager(args.address); + + case 'grantKeys': + return call.grantKeys(args.recipients, args.expirationTimestamps, args.keyManagers); + + case 'updateLockConfig': + return call.updateLockConfig(args.expirationDuration, args.maxNumberOfKeys, args.maxNumberOfKeysPerUser); + + case 'expireAndRefundFor': + return call.expireAndRefundFor(args.tokenId, args.refundAmount); + + case 'grantKeyExtension': + return call.grantKeyExtension(args.tokenId, args.duration); + + default: + throw `unknown proposal type ${proposal.type}`; + } +} + +main().then(() => { + console.log('successfully created the proposal(s)!'); +}); diff --git a/subgraph/README.md b/subgraph/README.md new file mode 100644 index 00000000..1f0f6534 --- /dev/null +++ b/subgraph/README.md @@ -0,0 +1,20 @@ +# Forta Subgraph +The Forta subgraph is currently hosted on chainstack (both dev and production enviornments) and provides visibility to on-chain events around the forta protocol such as staking, rewards, node pools, etc. + +## Deployment + +We use [theGraph's cli](https://thegraph.com/docs/en/deploying/deploying-a-subgraph-to-studio/#deploying-a-subgraph-to-subgraph-studio) in our development and production github actions to deploy the Forta subgraph. + +### Dev Deployment + +The development deployment occurs on every pull request that is merged to master via a github action. + +Dev subgraph url: `https://polygon-mumbai.graph-eu.p2pify.com/6dbdbeb3262ca5fa43773df1e690bd53/forta-dev` + +### Production Deployment + +There are two production subgraphs which we follow a [blue/green deployment pattern](https://www.redhat.com/en/topics/devops/what-is-blue-green-deployment) via a github action. + +Forta-a subgraph url: `https://polygon-mainnet.graph-eu.p2pify.com/49e5eba171ac70bd41578331e4d65cfc/forta-a` + +Forta-b subgraph url: `https://polygon-mainnet.graph-eu.p2pify.com/62563b45923ea9d259c5c16d1f73f804/forta-b` \ No newline at end of file diff --git a/subgraph/package.json b/subgraph/package.json index f8a0b6dd..8df9ea87 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -10,8 +10,9 @@ "prepare-dev:compile": "graph build subgraph.yaml --network mumbai", "prepare": "yarn prepare:schema && yarn prepare:codegen && yarn prepare:compile", "prepare-dev": "yarn prepare-dev:schema && yarn prepare-dev:codegen && yarn prepare-dev:compile", - "deploy-dev": "graph deploy --network mumbai --node https://api.thegraph.com/deploy/ ivandiazwm/forta-network-dev", - "deploy": "graph deploy --network matic --node https://api.thegraph.com/deploy/ forta-network/forta-network-a", + "deploy-dev": "graph deploy --node https://api.graph-eu.p2pify.com/765768b776199f59bb7f1bf37253e73f/deploy --ipfs https://api.graph-eu.p2pify.com/765768b776199f59bb7f1bf37253e73f/ipfs forta-dev", + "deploy": "graph deploy -l v0.0.1 --node https://api.graph-eu.p2pify.com/3e3485fa2703678549290ce52f45ef9c/deploy --ipfs https://api.graph-eu.p2pify.com/3e3485fa2703678549290ce52f45ef9c/ipfs forta-b", + "deploy-theGraph": "graph deploy --network matic --node https://api.thegraph.com/deploy/ forta-network/forta-network", "create-local": "graph create --node http://localhost:8020/ forta-network/forta-network", "remove-local": "graph remove --node http://localhost:8020/ forta-network/forta-network", "deploy-local": "graph deploy --node http://localhost:8020/ --ipfs http://localhost:5001 forta-network/forta-network", @@ -25,4 +26,4 @@ "matchstick-as": "^0.5.0", "source-map-support": "^0.5.21" } -} +} \ No newline at end of file diff --git a/subgraph/src/datasources/ScannerPoolRegistry.ts b/subgraph/src/datasources/ScannerPoolRegistry.ts index c1198148..652df906 100644 --- a/subgraph/src/datasources/ScannerPoolRegistry.ts +++ b/subgraph/src/datasources/ScannerPoolRegistry.ts @@ -76,6 +76,6 @@ export function handleScannerEnabled(event: ScannerEnabledEvent): void { export function handleTransfer(event: TransferEvent): void { const scannerPoolId = event.params.tokenId; const scannerPool = fetchScannerPool(scannerPoolId); - scannerPool.owner = event.params.to.toHexString(); + scannerPool.owner = fetchAccount(event.params.to).id; scannerPool.save(); } diff --git a/test/components/staking.delegation.js b/test/components/staking.delegation.test.js similarity index 99% rename from test/components/staking.delegation.js rename to test/components/staking.delegation.test.js index 7160684c..0e802ce9 100644 --- a/test/components/staking.delegation.js +++ b/test/components/staking.delegation.test.js @@ -551,4 +551,4 @@ describe('Staking - Delegation', function () { }); }); }); -}); +}); \ No newline at end of file diff --git a/test/components/staking.general.test.js b/test/components/staking.general.test.js index 71469382..866c970a 100644 --- a/test/components/staking.general.test.js +++ b/test/components/staking.general.test.js @@ -2,12 +2,19 @@ const { ethers } = require('hardhat'); const { expect } = require('chai'); const { prepare } = require('../fixture'); const { subjectToActive, subjectToInactive } = require('../../scripts/utils/staking.js'); +const { signERC712ScannerRegistration } = require('../../scripts/utils/scannerRegistration'); +const helpers = require('@nomicfoundation/hardhat-network-helpers'); const subjects = [ [ethers.BigNumber.from(ethers.utils.id('135a782d-c263-43bd-b70b-920873ed7e9d')), 1], // Agent id, agent type [ethers.BigNumber.from('1'), 2], // ScannerPool id, ScannerPool Type + [ethers.BigNumber.from('1'), 3], // ScannerPool id, ScannerPoolDelegator Type ]; -const [[subject1, subjectType1, active1, inactive1], [subject2, subjectType2, active2, inactive2]] = subjects.map((items) => [ +const [ + [subject1, subjectType1, active1, inactive1], + [subject2, subjectType2, active2, inactive2], + [/**subject3 === subject2*/, subjectType3, active3, inactive3] +] = subjects.map((items) => [ items[0], items[1], subjectToActive(items[1], items[0]), @@ -16,6 +23,9 @@ const [[subject1, subjectType1, active1, inactive1], [subject2, subjectType2, ac const MAX_STAKE = '10000'; +const ONE_DAY = 24 * 60 * 60; +const EPOCH_LENGTH = 7 * ONE_DAY; + describe('Forta Staking General', function () { prepare({ stake: { @@ -34,6 +44,11 @@ describe('Forta Staking General', function () { const args = [subject1, this.accounts.user1.address, 'Metadata1', [1, 3, 4, 5]]; await this.agents.connect(this.accounts.other).createAgent(...args); + + await this.scannerPools.connect(this.accounts.user1).registerScannerPool(subject2) + expect(await this.scannerPools.isRegistered(subject2)).to.be.equal(true); + expect(await this.scannerPools.ownerOf(subject2)).to.be.equal(this.accounts.user1.address); + expect(await this.scannerPools.monitoredChainId(subject2)).to.be.equal(1); }); describe('Freezing', function () { @@ -255,24 +270,45 @@ describe('Forta Staking General', function () { }); }); - describe.skip('token sweeping', async function () { + describe('token sweeping', async function () { beforeEach(async function () { + const network = await ethers.provider.getNetwork(); this.accounts.getAccount('slasher'); this.accounts.getAccount('sweeper'); + this.accounts.getAccount('scanner'); await this.access.connect(this.accounts.admin).grantRole(this.roles.SWEEPER, this.accounts.sweeper.address); await this.access.connect(this.accounts.admin).grantRole(this.roles.SLASHER, this.accounts.slasher.address); - this.staking.connect(this.accounts.user1).deposit(subjectType2, subject2, '100'); - this.staking.connect(this.accounts.user1).initiateWithdrawal(subjectType2, subject2, '50'); - this.staking.connect(this.accounts.user2).deposit(subjectType2, subject2, '100'); - this.staking.connect(this.accounts.user3).reward(subjectType2, subject2, '100'); - this.staking.connect(this.accounts.slasher).slash(subjectType2, subject2, '120', ethers.constants.AddressZero, '0'); + await this.staking.connect(this.accounts.user1).deposit(subjectType2, subject2, '100'); + + verifyingContractInfo = { + address: this.contracts.scannerPools.address, + chainId: network.chainId, + }; + scanner1Registration = { + scanner: this.accounts.scanner.address, + scannerPoolId: subject2, + chainId: 1, + metadata: 'metadata', + timestamp: (await ethers.provider.getBlock('latest')).timestamp, + }; + scanner1Signature = await signERC712ScannerRegistration(verifyingContractInfo, scanner1Registration, this.accounts.scanner); + await this.scannerPools.connect(this.accounts.user1).registerScannerNode(scanner1Registration, scanner1Signature) + + await this.staking.connect(this.accounts.user1).initiateWithdrawal(subjectType2, subject2, '50'); + await this.staking.connect(this.accounts.user2).deposit(subjectType3, subject2, '100'); + + const epoch = await this.rewardsDistributor.getCurrentEpochNumber(); + await helpers.time.increase(1 + EPOCH_LENGTH /* 1 week */); + + await this.rewardsDistributor.connect(this.accounts.manager).reward(subjectType2, subject2, '100', epoch); + await this.staking.connect(this.accounts.slasher).slash(subjectType2, subject2, '80', ethers.constants.AddressZero, '0'); }); it('sweep unrelated token', async function () { await expect(this.otherToken.connect(this.accounts.minter).mint(this.staking.address, '42')).to.be.not.reverted; - expect(await this.token.balanceOf(this.staking.address)).to.be.equal('180'); + expect(await this.token.balanceOf(this.staking.address)).to.be.equal('120'); expect(await this.otherToken.balanceOf(this.staking.address)).to.be.equal('42'); await expect(this.staking.connect(this.accounts.user1).sweep(this.otherToken.address, this.accounts.user1.address)).to.be.revertedWith( @@ -283,16 +319,16 @@ describe('Forta Staking General', function () { .to.emit(this.otherToken, 'Transfer') .withArgs(this.staking.address, this.accounts.sweeper.address, '42'); - expect(await this.token.balanceOf(this.staking.address)).to.be.equal('180'); + expect(await this.token.balanceOf(this.staking.address)).to.be.equal('120'); expect(await this.otherToken.balanceOf(this.staking.address)).to.be.equal('0'); }); it('sweep staked token', async function () { - expect(await this.token.balanceOf(this.staking.address)).to.be.equal('180'); + expect(await this.token.balanceOf(this.staking.address)).to.be.equal('120'); await expect(this.token.connect(this.accounts.user3).transfer(this.staking.address, '17')).to.be.not.reverted; - expect(await this.token.balanceOf(this.staking.address)).to.be.equal('197'); + expect(await this.token.balanceOf(this.staking.address)).to.be.equal('137'); await expect(this.staking.connect(this.accounts.user1).sweep(this.token.address, this.accounts.user1.address)).to.be.revertedWith( `MissingRole("${this.roles.SWEEPER}", "${this.accounts.user1.address}")` @@ -302,62 +338,105 @@ describe('Forta Staking General', function () { .to.emit(this.token, 'Transfer') .withArgs(this.staking.address, this.accounts.sweeper.address, '17'); - expect(await this.token.balanceOf(this.staking.address)).to.be.equal('180'); + expect(await this.token.balanceOf(this.staking.address)).to.be.equal('120'); }); }); - describe.skip('attack scenario', function () { + describe('attack scenario', function () { it('dusting', async function () { - await this.agents.connect(this.accounts.manager).setStakeThreshold({ max: ethers.utils.parseEther('5000'), min: '1', activated: true }); + await this.token.connect(this.accounts.minter).mint(this.rewardsDistributor.address, ethers.utils.parseEther('1000')); + + const network = await ethers.provider.getNetwork(); + this.accounts.getAccount('scanner'); const legitimate = this.accounts.user1; const attacker = this.accounts.user2; + await this.staking.connect(legitimate).deposit(subjectType2, subject2, '10000000000000'); + + verifyingContractInfo = { + address: this.contracts.scannerPools.address, + chainId: network.chainId, + }; + scanner1Registration = { + scanner: this.accounts.scanner.address, + scannerPoolId: subject2, + chainId: 1, + metadata: 'metadata', + timestamp: (await ethers.provider.getBlock('latest')).timestamp, + }; + scanner1Signature = await signERC712ScannerRegistration(verifyingContractInfo, scanner1Registration, this.accounts.scanner); + await this.scannerPools.connect(legitimate).registerScannerNode(scanner1Registration, scanner1Signature); + + await helpers.time.increase(1 + EPOCH_LENGTH /* 1 week */); + + const epoch = await this.rewardsDistributor.getCurrentEpochNumber(); + { const totalShares = await this.staking.totalShares(subjectType2, subject2).then((x) => x.toNumber()); + const totalDelegatorShares = await this.staking.totalShares(subjectType3, subject2).then((x) => x.toNumber()); const shares = await this.staking.sharesOf(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - const availableReward = await this.staking.availableReward(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - console.table({ totalShares, shares, availableReward }); + const delegatorShares = await this.staking.sharesOf(subjectType3, subject2, attacker.address).then((x) => x.toNumber()); + const availableReward = await this.rewardsDistributor.availableReward(subjectType2, subject2, epoch, legitimate.address).then((x) => x.toNumber()); + console.table({ totalShares, totalDelegatorShares, shares, delegatorShares, availableReward }); } await this.staking.connect(legitimate).deposit(subjectType2, subject2, '20000000000000'); { const totalShares = await this.staking.totalShares(subjectType2, subject2).then((x) => x.toNumber()); + const totalDelegatorShares = await this.staking.totalShares(subjectType3, subject2).then((x) => x.toNumber()); const shares = await this.staking.sharesOf(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - const availableReward = await this.staking.availableReward(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - console.table({ totalShares, shares, availableReward }); + const delegatorShares = await this.staking.sharesOf(subjectType3, subject2, attacker.address).then((x) => x.toNumber()); + const availableReward = await this.rewardsDistributor.availableReward(subjectType2, subject2, epoch, legitimate.address).then((x) => x.toNumber()); + console.table({ totalShares, totalDelegatorShares, shares, delegatorShares, availableReward}); } - await this.staking.connect(legitimate).reward(subjectType2, subject2, '10000000000000'); + await this.staking.connect(attacker).deposit(subjectType3, subject2, '3'); + await helpers.time.increase(1 + EPOCH_LENGTH /* 1 week */); { const totalShares = await this.staking.totalShares(subjectType2, subject2).then((x) => x.toNumber()); + const totalDelegatorShares = await this.staking.totalShares(subjectType3, subject2).then((x) => x.toNumber()); const shares = await this.staking.sharesOf(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - const availableReward = await this.staking.availableReward(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - console.table({ totalShares, shares, availableReward }); + const delegatorShares = await this.staking.sharesOf(subjectType3, subject2, attacker.address).then((x) => x.toNumber()); + const availableReward = await this.rewardsDistributor.availableReward(subjectType2, subject2, epoch, legitimate.address).then((x) => x.toNumber()); + console.table({ totalShares, totalDelegatorShares, shares, delegatorShares, availableReward }); } - await this.staking.connect(attacker).deposit(subjectType2, subject2, '3'); + await this.rewardsDistributor.connect(this.accounts.manager).reward(subjectType2, subject2, '10000000000000', epoch); { const totalShares = await this.staking.totalShares(subjectType2, subject2).then((x) => x.toNumber()); + const totalDelegatorShares = await this.staking.totalShares(subjectType3, subject2).then((x) => x.toNumber()); const shares = await this.staking.sharesOf(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - const availableReward = await this.staking.availableReward(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - console.table({ totalShares, shares, availableReward }); + const delegatorShares = await this.staking.sharesOf(subjectType3, subject2, attacker.address).then((x) => x.toNumber()); + const availableReward = await this.rewardsDistributor.availableReward(subjectType2, subject2, epoch, legitimate.address).then((x) => x.toNumber()); + console.table({ totalShares, totalDelegatorShares, shares, delegatorShares, availableReward }); } - await this.staking.connect(attacker).initiateWithdrawal(subjectType2, subject2, '2'); - await this.staking.connect(attacker).initiateWithdrawal(subjectType2, subject2, '1'); + await this.staking.connect(attacker).initiateWithdrawal(subjectType3, subject2, '2'); + await this.staking.connect(attacker).initiateWithdrawal(subjectType3, subject2, '1'); { const totalShares = await this.staking.totalShares(subjectType2, subject2).then((x) => x.toNumber()); + const totalDelegatorShares = await this.staking.totalShares(subjectType3, subject2).then((x) => x.toNumber()); const shares = await this.staking.sharesOf(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - const availableReward = await this.staking.availableReward(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); - console.table({ totalShares, shares, availableReward }); + const delegatorShares = await this.staking.sharesOf(subjectType3, subject2, attacker.address).then((x) => x.toNumber()); + const availableReward = await this.rewardsDistributor.availableReward(subjectType2, subject2, epoch, legitimate.address).then((x) => x.toNumber()); + console.table({ totalShares, totalDelegatorShares, shares, delegatorShares, availableReward }); } - await this.staking.releaseReward(subjectType2, subject2, legitimate.address); + await this.rewardsDistributor.connect(legitimate).claimRewards(subjectType2, subject2, [epoch]); + + { + const totalShares = await this.staking.totalShares(subjectType2, subject2).then((x) => x.toNumber()); + const totalDelegatorShares = await this.staking.totalShares(subjectType3, subject2).then((x) => x.toNumber()); + const shares = await this.staking.sharesOf(subjectType2, subject2, legitimate.address).then((x) => x.toNumber()); + const delegatorShares = await this.staking.sharesOf(subjectType3, subject2, attacker.address).then((x) => x.toNumber()); + const availableReward = await this.rewardsDistributor.availableReward(subjectType2, subject2, epoch, legitimate.address).then((x) => x.toNumber()); + console.table({ totalShares, totalDelegatorShares, shares, delegatorShares, availableReward }); + } }); }); }); \ No newline at end of file