From 83cd36dfc3e45e5835e863da0b5b74dfd5471df2 Mon Sep 17 00:00:00 2001 From: Felipe Mendes Date: Wed, 5 Apr 2023 11:48:56 -0300 Subject: [PATCH] feat: design ens verification flow (#193) * wip: add base solidity functions to try ens validation * chore: add hardhat fork setup with env variable * wip: setup ens verification for FleekERC721 * wip: add ens namehash generation * chore: gas report setting * feat: add ens verification on setTokenENS function * test: hardhat transfer ens owner to set new ens * test: fix foundry tests to enable ens validation * refactor: change back ens to calldata and split out a public function for namehash testing * refactor: move FleekENS.sol to util folder * test: add ens validation tests for not owner attempts * chore: add mainnet api key env in ci * chore: fix .env.example * fix: remove extra unused file --- .github/workflows/contract.yml | 2 + contracts/.env.example | 11 +++- contracts/.gitignore | 3 +- contracts/contracts/FleekERC721.sol | 11 ++-- contracts/contracts/util/FleekENS.sol | 32 +++++++++++ contracts/foundry.toml | 5 ++ contracts/hardhat.config.ts | 12 +++- contracts/package.json | 6 +- .../foundry/FleekERC721/AccessControl.t.sol | 5 +- .../test/foundry/FleekERC721/Constants.sol | 3 - contracts/test/foundry/FleekERC721/ENS.t.sol | 32 +++++++++++ .../test/foundry/FleekERC721/GetToken.t.sol | 9 +-- contracts/test/foundry/FleekERC721/Mint.t.sol | 4 ++ .../test/foundry/FleekERC721/TestBase.sol | 11 ++++ .../test/foundry/FleekERC721/TokenURI.t.sol | 6 +- contracts/test/foundry/FleekERC721/Utils.sol | 16 ++++++ .../hardhat/contracts/FleekERC721/ens.t.ts | 56 +++++++++++++++++++ .../contracts/FleekERC721/helpers/errors.ts | 1 + .../contracts/FleekERC721/helpers/fixture.ts | 3 + .../contracts/FleekERC721/helpers/utils.ts | 29 ++++++++++ .../FleekERC721/update-properties.t.ts | 8 ++- contracts/yarn.lock | 49 ++++++++++++++++ 22 files changed, 291 insertions(+), 23 deletions(-) create mode 100644 contracts/contracts/util/FleekENS.sol create mode 100644 contracts/test/foundry/FleekERC721/ENS.t.sol create mode 100644 contracts/test/foundry/FleekERC721/Utils.sol create mode 100644 contracts/test/hardhat/contracts/FleekERC721/ens.t.ts diff --git a/.github/workflows/contract.yml b/.github/workflows/contract.yml index dfa087c..3acf54a 100644 --- a/.github/workflows/contract.yml +++ b/.github/workflows/contract.yml @@ -11,6 +11,8 @@ on: jobs: test-contracts: runs-on: ubuntu-latest + env: + MAINNET_API_KEY: ${{ secrets.MAINNET_API_KEY }} defaults: run: diff --git a/contracts/.env.example b/contracts/.env.example index f4e6b94..a6e0467 100644 --- a/contracts/.env.example +++ b/contracts/.env.example @@ -9,4 +9,13 @@ PRIVATE_KEY= POLYSCAN_API=https://mumbai.polygonscan.com/ # The address of the deployed contract on the blockchain -CONTRACT_ADDRESS= \ No newline at end of file +CONTRACT_ADDRESS= + +# Alchemy or Infura API key to fork the mainnet on tests (e.g. https://eth-mainnet.g.alchemy.com/v2/your-api-key) +MAINNET_API_KEY= + +# Enable gas report on hardhat tests +REPORT_GAS=true + +# The CoinMarketCap API key to get the price of the token for gas report +COINMARKETCAP_KEY= \ No newline at end of file diff --git a/contracts/.gitignore b/contracts/.gitignore index c5dce6a..b9e5676 100644 --- a/contracts/.gitignore +++ b/contracts/.gitignore @@ -2,10 +2,11 @@ cache artifacts deployments/hardhat +gas-report # Foundry out forge-cache # OpenZeppelin -.openzeppelin/unknown-*.json +.openzeppelin/unknown-*.json \ No newline at end of file diff --git a/contracts/contracts/FleekERC721.sol b/contracts/contracts/FleekERC721.sol index dc7a85a..d42bf78 100644 --- a/contracts/contracts/FleekERC721.sol +++ b/contracts/contracts/FleekERC721.sol @@ -9,6 +9,7 @@ import "./FleekAccessControl.sol"; import "./FleekBilling.sol"; import "./FleekPausable.sol"; import "./FleekAccessPoints.sol"; +import "./util/FleekENS.sol"; import "./util/FleekStrings.sol"; import "./IERCX.sol"; @@ -104,7 +105,7 @@ contract FleekERC721 is string memory name, string memory description, string memory externalURL, - string memory ENS, + string calldata ens, string memory commitHash, string memory gitRepository, string memory logo, @@ -112,6 +113,7 @@ contract FleekERC721 is bool accessPointAutoApproval, address verifier ) public payable requirePayment(Billing.Mint) returns (uint256) { + FleekENS.requireENSOwner(ens); uint256 tokenId = _appIds; _mint(to, tokenId); @@ -121,7 +123,7 @@ contract FleekERC721 is app.name = name; app.description = description; app.externalURL = externalURL; - app.ENS = ENS; + app.ENS = ens; app.logo = logo; app.color = color; @@ -134,7 +136,7 @@ contract FleekERC721 is name, description, externalURL, - ENS, + ens, commitHash, gitRepository, logo, @@ -274,8 +276,9 @@ contract FleekERC721 is */ function setTokenENS( uint256 tokenId, - string memory _tokenENS + string calldata _tokenENS ) public virtual requireTokenRole(tokenId, TokenRoles.Controller) { + FleekENS.requireENSOwner(_tokenENS); _requireMinted(tokenId); _apps[tokenId].ENS = _tokenENS; emit MetadataUpdate(tokenId, "ENS", _tokenENS, msg.sender); diff --git a/contracts/contracts/util/FleekENS.sol b/contracts/contracts/util/FleekENS.sol new file mode 100644 index 0000000..d101849 --- /dev/null +++ b/contracts/contracts/util/FleekENS.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import {ENS} from "@ensdomains/ens-contracts/contracts/registry/ENS.sol"; +import {Resolver} from "@ensdomains/ens-contracts/contracts/resolvers/Resolver.sol"; + +error MustBeENSOwner(); + +library FleekENS { + ENS internal constant _ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e); + + /** + * @dev Reverts if the sender is not the owner of the ENS node. + */ + function requireENSOwner(string calldata name) internal view { + if (_ens.owner(namehash(bytes(name), 0)) != msg.sender) revert MustBeENSOwner(); + } + + /** + * @dev Processes the name and returns the ENS node hash. + */ + function namehash(bytes calldata name, uint256 index) internal view returns (bytes32) { + for (uint256 i = index; i < name.length; i++) { + if (name[i] == ".") { + return keccak256(abi.encodePacked(namehash(name, i + 1), keccak256(name[index:i]))); + } + } + return keccak256(abi.encodePacked(bytes32(0x0), keccak256(name[index:name.length]))); + } +} diff --git a/contracts/foundry.toml b/contracts/foundry.toml index db698f2..65fa18e 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -4,3 +4,8 @@ out = 'out' libs = ['node_modules', 'lib'] test = 'test/foundry' cache_path = 'forge-cache' +via_ir = true + +[rpc_endpoints] +mainnet = "${MAINNET_API_KEY}" + diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index bfeb00f..f46936b 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -18,6 +18,8 @@ const { PRIVATE_KEY, REPORT_GAS, POLYGONSCAN_KEY, + MAINNET_API_KEY, + COINMARKETCAP_KEY, } = process.env; const config: HardhatUserConfig = { @@ -25,6 +27,12 @@ const config: HardhatUserConfig = { networks: { hardhat: { chainId: 31337, + forking: MAINNET_API_KEY + ? { + url: MAINNET_API_KEY, + blockNumber: 16876149, + } + : undefined, }, mumbai: { url: API_URL, @@ -35,9 +43,9 @@ const config: HardhatUserConfig = { gasReporter: { enabled: REPORT_GAS === 'true' || false, currency: 'USD', - outputFile: 'gas-report.txt', + outputFile: 'gas-report', noColors: true, - // coinmarketcap: process.env.COINMARKETCAP_API_KEY, + coinmarketcap: COINMARKETCAP_KEY, }, contractSizer: { runOnCompile: false, diff --git a/contracts/package.json b/contracts/package.json index 70ccae0..fe8b160 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -4,8 +4,8 @@ "description": "", "private": "false", "scripts": { - "test": "hardhat test && forge test --via-ir", - "test:foundry": "forge test --via-ir -vvv", + "test": "yarn test:hardhat && yarn test:foundry", + "test:foundry": "forge test -vvv --fork-url mainnet --fork-block-number 16876149", "test:hardhat": "hardhat test", "format": "prettier --write \"./**/*.{js,json,sol,ts}\"", "node:hardhat": "hardhat node", @@ -25,6 +25,8 @@ }, "homepage": "https://github.com/fleekxyz/non-fungible-apps#readme", "devDependencies": { + "@ensdomains/ens-contracts": "^0.0.20", + "@ensdomains/eth-ens-namehash": "^2.0.15", "@nomicfoundation/hardhat-chai-matchers": "^1.0.5", "@nomicfoundation/hardhat-network-helpers": "^1.0.7", "@nomicfoundation/hardhat-toolbox": "^2.0.0", diff --git a/contracts/test/foundry/FleekERC721/AccessControl.t.sol b/contracts/test/foundry/FleekERC721/AccessControl.t.sol index 08c9167..71fdb29 100644 --- a/contracts/test/foundry/FleekERC721/AccessControl.t.sol +++ b/contracts/test/foundry/FleekERC721/AccessControl.t.sol @@ -162,6 +162,7 @@ contract Test_FleekERC721_AccessControl is Test_FleekERC721_Base, Test_FleekERC7 function test_mint() public { // Anyone can mint + transferENS(TestConstants.APP_ENS, anyAddress); vm.startPrank(anyAddress); mintDefault(address(99)); vm.stopPrank(); @@ -201,7 +202,7 @@ contract Test_FleekERC721_AccessControl is Test_FleekERC721_Base, Test_FleekERC7 } function test_setTokenENS() public { - string memory ens = "ens"; + string memory ens = "ens.eth"; // ColletionOwner vm.prank(collectionOwner); @@ -214,10 +215,12 @@ contract Test_FleekERC721_AccessControl is Test_FleekERC721_Base, Test_FleekERC7 CuT.setTokenENS(tokenId, ens); // TokenOwner + transferENS(ens, tokenOwner); vm.prank(tokenOwner); CuT.setTokenENS(tokenId, ens); // TokenController + transferENS(ens, tokenController); vm.prank(tokenController); CuT.setTokenENS(tokenId, ens); diff --git a/contracts/test/foundry/FleekERC721/Constants.sol b/contracts/test/foundry/FleekERC721/Constants.sol index 00dcd17..bd89a10 100644 --- a/contracts/test/foundry/FleekERC721/Constants.sol +++ b/contracts/test/foundry/FleekERC721/Constants.sol @@ -24,7 +24,4 @@ library TestConstants { string public constant LOGO_1 = "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IiB2aWV3Qm94PSIwIDAgMTAwMCAxMDAwIiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCAxMDAwIDEwMDAiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8Zz48cGF0aCBkPSJNNTAwLDEwQzIyOS40LDEwLDEwLDIyOS40LDEwLDUwMGMwLDI3MC42LDIxOS40LDQ5MCw0OTAsNDkwYzI3MC42LDAsNDkwLTIxOS40LDQ5MC00OTBDOTkwLDIyOS40LDc3MC42LDEwLDUwMCwxMHogTTgxNSw4MTVjLTQwLjksNDAuOS04OC42LDczLjEtMTQxLjYsOTUuNWMtNTQuOSwyMy4yLTExMy4yLDM1LTE3My40LDM1Yy02MC4yLDAtMTE4LjUtMTEuOC0xNzMuNC0zNUMyNzMuNiw4ODgsMjI1LjksODU1LjksMTg1LDgxNXMtNzMtODguNi05NS41LTE0MS42Yy0yMy4yLTU0LjktMzUtMTEzLjItMzUtMTczLjRjMC02MC4yLDExLjgtMTE4LjUsMzUtMTczLjRjMjIuNC01Myw1NC42LTEwMC43LDk1LjUtMTQxLjZzODguNi03MywxNDEuNi05NS41YzU0LjktMjMuMiwxMTMuMi0zNSwxNzMuNC0zNWM2MC4yLDAsMTE4LjUsMTEuOCwxNzMuNCwzNWM1MywyMi40LDEwMC43LDU0LjYsMTQxLjYsOTUuNWM0MC45LDQwLjksNzMsODguNiw5NS41LDE0MS42YzIzLjIsNTQuOSwzNSwxMTMuMiwzNSwxNzMuNGMwLDYwLjItMTEuOCwxMTguNS0zNSwxNzMuNEM4ODgsNzI2LjQsODU1LjksNzc0LjEsODE1LDgxNXoiLz48L2c+Cjwvc3ZnPg=="; - - string public constant DEFAULT_TOKEN_URI = - "data:application/json;base64,eyJuYW1lIjoiTmV3IEFwcCBOYW1lIiwiZGVzY3JpcHRpb24iOiJOZXcgZGVzY3JpcHRpb24gZm9yIHRoZSBhcHAuIiwib3duZXIiOiIweDM0YTFkM2ZmZjM5NTg4NDNjNDNhZDgwZjMwYjk0YzUxMDY0NWMzMTYiLCJleHRlcm5hbF91cmwiOiJodHRwczovL25ldy11cmwuY29tIiwiaW1hZ2UiOiJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUIzYVdSMGFEMGlNVEEyTlNJZ2FHVnBaMmgwUFNJeE1EWTFJaUIyYVdWM1FtOTRQU0l3SURBZ01UQTJOU0F4TURZMUlpQm1hV3hzUFNKdWIyNWxJaUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSGh0Ykc1ek9uaHNhVzVyUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMM2hzYVc1cklqNDhjM1I1YkdVZ2RIbHdaVDBpZEdWNGRDOWpjM01pUGtCcGJYQnZjblFnZFhKc0tDSm9kSFJ3Y3pvdkwyWnZiblJ6TG1kdmIyZHNaV0Z3YVhNdVkyOXRMMk56Y3pJL1ptRnRhV3g1UFVsdWRHVnlPbmRuYUhSQU5UQXdPell3TUNJcE96d3ZjM1I1YkdVK1BISmxZM1FnZDJsa2RHZzlJakV3TmpVaUlHaGxhV2RvZEQwaU1UQTJOU0lnWm1sc2JEMGlkWEpzS0NOaVlXTnJaM0p2ZFc1a0tTSWdMejQ4Y21WamRDQnZjR0ZqYVhSNVBTSXdMaklpSUhkcFpIUm9QU0l4TURZMUlpQm9aV2xuYUhROUlqRXdOalVpSUdacGJHdzlJblZ5YkNnalltRmphMmR5YjNWdVpDMXlZV1JwWVd3cElpQXZQanhuSUdacGJIUmxjajBpZFhKc0tDTmthWE5yWlhSMFpTMXphR0ZrYjNjcElqNDhjR0YwYUNCa1BTSk5PRFUzTGpJek1TQXlOemt1TnpFeVREa3dNaTR5TkNBeU9EWXVOamMxUXpreE1DNDFORGNnTWpnM0xqazJJRGt4Tnk0NU1UVWdNamt5TGpjeU1TQTVNakl1TlNBeU9Ua3VOelk0VERrek9DNDRPVFFnTXpJMExqazJORU01TkRJdU1qUTVJRE16TUM0eE1pQTVORE11TXpFeElETXpOaTQwTXpjZ09UUXhMamd5TnlBek5ESXVOREEyVERrek55NDNPVGdnTXpVNExqWXhOVXc1TWpRdU1EUTVJRE0xTmk0Mk5VdzVNVGt1TkRFMklETTNOQzR3T0RSTU9UTTBMakEyT0NBek56WXVNalJNTnpreExqazBOeUE1TWpJdU1UVXlRemM0T0M0eE1Ea2dPVE0yTGpnNU5pQTNOek11TmprMElEazBOaTR6TURnZ056VTRMalkxTVNBNU5ETXVPRGt6VERFM09TNDJNellnT0RVd0xqa3lPRU14TmpJdU16RTRJRGcwT0M0eE5EY2dNVFV4TGpJeE5TQTRNekF1T1RnM0lERTFOUzQzTnpZZ09ERTBMakExTVV3eE5qQXVORGM0SURjNU5pNDFPVXczTURRdU16RTFJRGczT1M0MU56Uk1PRFUzTGpJek1TQXlOemt1TnpFeVdpSWdabWxzYkQwaUl6QTFNRFV3TlNJZ0x6NDhMMmMrUEhCaGRHZ2daRDBpVFRnME1DNHlNekVnTWpRd0xqY3hNa3c0T0RVdU1qUWdNalEzTGpZM05VTTRPVE11TlRRM0lESTBPQzQ1TmpFZ09UQXdMamt4TlNBeU5UTXVOekl5SURrd05TNDFJREkyTUM0M05qaE1PVEl4TGpnNU5DQXlPRFV1T1RZMVF6a3lOUzR5TkRrZ01qa3hMakV5SURreU5pNHpNVEVnTWprM0xqUXpOeUE1TWpRdU9ESTNJRE13TXk0ME1EWk1PVEl3TGpjNU9DQXpNVGt1TmpFMlREa3dOeTR3TkRrZ016RTNMalkxVERrd01pNDBNVFlnTXpNMUxqQTRORXc1TVRjdU1EWTRJRE16Tnk0eU5ERk1OemMwTGprME55QTRPRE11TVRVeVF6YzNNUzR4TURrZ09EazNMamc1TmlBM05UWXVOamswSURrd055NHpNRGdnTnpReExqWTFNU0E1TURRdU9Ea3pUREUyTWk0Mk16WWdPREV4TGpreU9FTXhORFV1TXpFNElEZ3dPUzR4TkRjZ01UTTBMakl4TlNBM09URXVPVGczSURFek9DNDNOellnTnpjMUxqQTFNVXd4TkRNdU5EYzRJRGMxTnk0MU9VdzJPRGN1TXpFMUlEZzBNQzQxTnpSTU9EUXdMakl6TVNBeU5EQXVOekV5V2lJZ1ptbHNiRDBpZFhKc0tDTnRZV2x1S1NJZ0x6NDhjR0YwYUNCbWFXeHNMWEoxYkdVOUltVjJaVzV2WkdRaUlHTnNhWEF0Y25Wc1pUMGlaWFpsYm05a1pDSWdaRDBpVFRNeE9TNDRORGNnTVRZeExqVXdNa016TVRBdU16VTJJREUyTUM0d01EY2dNekF3TGpZM05DQXhOall1TXpJMklESTVPQzR5TWpFZ01UYzFMall4Tmt3eE16Z3VOekkwSURjM09TNDNOVGhETVRNMkxqSTNNU0EzT0RrdU1EUTRJREUwTVM0NU56Y2dOemszTGpjNUlERTFNUzQwTmpnZ056azVMakk0TlV3M05EQXVNRFl4SURnNU1TNDVOek5ETnpRNUxqVTFNeUE0T1RNdU5EWTNJRGMxT1M0eU16VWdPRGczTGpFME9DQTNOakV1TmpnM0lEZzNOeTQ0TlRoTU9UQXlMalF3TlNBek5EUXVPRFUwVERnNE9TNHhOVGdnTXpReUxqYzJPRXc0T1RndU9EY3lJRE13TlM0NU56Sk1PVEV5TGpFeE9TQXpNRGd1TURVNVREa3hNeTQzTXpNZ016QXhMamswTmtNNU1UUXVPRE0zSURJNU55NDNOaklnT1RFMExqTXdPU0F5T1RNdU5EYzJJRGt4TWk0eU5URWdNamc1TGpreU4wdzRPVE11TkRnMElESTFOeTQxTmpsRE9Ea3hMakUxTXlBeU5UTXVOVFE1SURnNE55NHdOak1nTWpVd0xqZ3lNeUE0T0RJdU1qSXhJREkxTUM0d05qRk1PREk0TGpJd05TQXlOREV1TlRVMFF6Z3lNaTR5TWpRZ01qUXdMall4TXlBNE1UVXVPRFk1SURJME1pNDNPRE1nT0RFeExqUXlOeUF5TkRjdU1qZzBURGd3TlM0Mk9EWWdNalV6TGpFd00wTTRNRFF1TWpBMUlESTFOQzQyTURNZ09EQXlMakE0TnlBeU5UVXVNekkySURnd01DNHdPVE1nTWpVMUxqQXhNMHczT0RNdU5qRXhJREkxTWk0ME1UZE1Oek0wTGpNZ05ETTVMakU1TmtNM016RXVORE01SURRMU1DNHdNelVnTnpJd0xqRTBNeUEwTlRjdU5EQTNJRGN3T1M0d055QTBOVFV1TmpZelRETXlPQzQ0TkRjZ016azFMamM0T0VNek1UY3VOemMwSURNNU5DNHdORFVnTXpFeExqRXhOeUF6T0RNdU9EUTFJRE14TXk0NU56Z2dNemN6TGpBd04wd3pOall1TlRJNElERTNNeTQ1TmpKTU16WTJMalV6TXlBeE56TXVPVFF4UXpNMk55NHlNelFnTVRjeExqSTBJRE0yTlM0MU56SWdNVFk0TGpjd01pQXpOakl1T0RFZ01UWTRMakkyTjB3ek1Ua3VPRFEzSURFMk1TNDFNREphVFRNMk9TNHpPVElnTVRjMExqUXhORXd6TmpndU5qVXlJREUzTnk0eU1UZE1NekUyTGpnME15QXpOek11TkRVNFF6TXhOQzR6T1NBek9ESXVOelE0SURNeU1DNHdPVFlnTXpreExqUTVJRE15T1M0MU9EY2dNemt5TGprNE5VdzNNRGt1T0RFZ05EVXlMamcyUXpjeE9TNHpNREVnTkRVMExqTTFOQ0EzTWpndU9UZ3pJRFEwT0M0d016VWdOek14TGpRek5pQTBNemd1TnpRMVREYzRNQzQzTkRjZ01qVXhMamsyTmt3M09ETXVNalExSURJME1pNDFNRFJNTnpnekxqazROU0F5TXprdU56QXhURE0yT1M0ek9USWdNVGMwTGpReE5Gb2lJR1pwYkd3OUlpTXhNekV6TVRZaUlDOCtQSEJoZEdnZ1ptbHNiQzF5ZFd4bFBTSmxkbVZ1YjJSa0lpQmpiR2x3TFhKMWJHVTlJbVYyWlc1dlpHUWlJSE4wY205clpUMGlkWEpzS0NOdFlXbHVLU0lnYzNSeWIydGxMWGRwWkhSb1BTSTBJaUJ6ZEhKdmEyVXRiR2x1WldOaGNEMGljbTkxYm1RaUlITjBjbTlyWlMxc2FXNWxhbTlwYmowaWNtOTFibVFpSUdROUlrMHpNVGt1T0RRM0lERTJNUzQxTURKRE16RXdMak0xTmlBeE5qQXVNREEzSURNd01DNDJOelFnTVRZMkxqTXlOaUF5T1RndU1qSXhJREUzTlM0Mk1UWk1NVE00TGpjeU5DQTNOemt1TnpVNFF6RXpOaTR5TnpFZ056ZzVMakEwT0NBeE5ERXVPVGMzSURjNU55NDNPU0F4TlRFdU5EWTRJRGM1T1M0eU9EVk1OelF3TGpBMk1TQTRPVEV1T1RjelF6YzBPUzQxTlRNZ09Ea3pMalEyTnlBM05Ua3VNak0xSURnNE55NHhORGdnTnpZeExqWTROeUE0TnpjdU9EVTRURGt3TWk0ME1EVWdNelEwTGpnMU5FdzRPRGt1TVRVNElETTBNaTQzTmpoTU9EazRMamczTWlBek1EVXVPVGN5VERreE1pNHhNVGtnTXpBNExqQTFPVXc1TVRNdU56TXpJRE13TVM0NU5EWkRPVEUwTGpnek55QXlPVGN1TnpZeUlEa3hOQzR6TURrZ01qa3pMalEzTmlBNU1USXVNalV4SURJNE9TNDVNamRNT0RrekxqUTROQ0F5TlRjdU5UWTVRemc1TVM0eE5UTWdNalV6TGpVME9TQTRPRGN1TURZeklESTFNQzQ0TWpNZ09EZ3lMakl5TVNBeU5UQXVNRFl4VERneU9DNHlNRFVnTWpReExqVTFORU00TWpJdU1qSTBJREkwTUM0Mk1UTWdPREUxTGpnMk9TQXlOREl1TnpneklEZ3hNUzQwTWpjZ01qUTNMakk0TkV3NE1EVXVOamcySURJMU15NHhNRE5ET0RBMExqSXdOU0F5TlRRdU5qQXpJRGd3TWk0d09EY2dNalUxTGpNeU5pQTRNREF1TURreklESTFOUzR3TVROTU56Z3pMall4TVNBeU5USXVOREUzVERjek5DNHpJRFF6T1M0eE9UWkROek14TGpRek9TQTBOVEF1TURNMUlEY3lNQzR4TkRNZ05EVTNMalF3TnlBM01Ea3VNRGNnTkRVMUxqWTJNMHd6TWpndU9EUTNJRE01TlM0M09EaERNekUzTGpjM05DQXpPVFF1TURRMUlETXhNUzR4TVRjZ016Z3pMamcwTlNBek1UTXVPVGM0SURNM015NHdNRGRNTXpZMkxqVXlPQ0F4TnpNdU9UWXlURE0yTmk0MU16TWdNVGN6TGprME1VTXpOamN1TWpNMElERTNNUzR5TkNBek5qVXVOVGN5SURFMk9DNDNNRElnTXpZeUxqZ3hJREUyT0M0eU5qZE1NekU1TGpnME55QXhOakV1TlRBeVdrMHpOamt1TXpreUlERTNOQzQwTVRSTU16WTRMalkxTWlBeE56Y3VNakUzVERNeE5pNDRORE1nTXpjekxqUTFPRU16TVRRdU16a2dNemd5TGpjME9DQXpNakF1TURrMklETTVNUzQwT1NBek1qa3VOVGczSURNNU1pNDVPRFZNTnpBNUxqZ3hJRFExTWk0NE5rTTNNVGt1TXpBeElEUTFOQzR6TlRRZ056STRMams0TXlBME5EZ3VNRE0xSURjek1TNDBNellnTkRNNExqYzBOVXczT0RBdU56UTNJREkxTVM0NU5qWk1Oemd6TGpJME5TQXlOREl1TlRBMFREYzRNeTQ1T0RVZ01qTTVMamN3TVV3ek5qa3VNemt5SURFM05DNDBNVFJhSWlCbWFXeHNQU0oxY213b0kyUnBjMnRsZEhSbExXZHlZV1JwWlc1MEtTSWdabWxzYkMxdmNHRmphWFI1UFNJd0xqSWlJQzgrUEhCaGRHZ2daRDBpVFRNek5TNHpPQ0F5TURndU1URXpRek16TlM0NU1qSWdNakE0TGpFNU9DQXpNell1TkRFM0lESXdOeTQyT0RZZ016TTJMakk0TXlBeU1EY3VNVGM1VERNek1DNHpPU0F4T0RRdU56azFRek16TUM0eU5Ea2dNVGcwTGpJMk1TQXpNamt1TlRJNUlERTROQzR4TkRnZ016STVMakV5T1NBeE9EUXVOVGszVERNeE1pNHpOVGdnTWpBekxqUXhNVU16TVRFdU9UYzRJREl3TXk0NE16Z2dNekV5TGpFM05DQXlNRFF1TkRVNElETXhNaTQzTVRZZ01qQTBMalUwTkV3ek1UY3VPVFl5SURJd05TNHpOME16TVRndU16VTNJREl3TlM0ME16SWdNekU0TGpVNU5TQXlNRFV1TnprMklETXhPQzQwT1RNZ01qQTJMakU0TTB3ek1UUXVOeUF5TWpBdU5UVXhRek14TkM0MU9UY2dNakl3TGprek9DQXpNVFF1T0RNMUlESXlNUzR6TURJZ016RTFMakl6TVNBeU1qRXVNelkwVERNeU5DNDFNemtnTWpJeUxqZ3pRek15TkM0NU16VWdNakl5TGpnNU15QXpNalV1TXpNNElESXlNaTQyTWprZ016STFMalEwSURJeU1pNHlOREpNTXpJNUxqSXpNeUF5TURjdU9EYzFRek15T1M0ek16WWdNakEzTGpRNE9DQXpNamt1TnpNNUlESXdOeTR5TWpRZ016TXdMakV6TlNBeU1EY3VNamcyVERNek5TNHpPQ0F5TURndU1URXpXaUlnWm1sc2JEMGlkWEpzS0NOdFlXbHVLU0lnTHo0OGNHRjBhQ0JrUFNKTk16RTVMakk0TWlBeU5qa3VNRGczUXpNeE9TNDRNalFnTWpZNUxqRTNNeUF6TWpBdU16RTVJREkyT0M0Mk5qRWdNekl3TGpFNE5pQXlOamd1TVRVMFRETXhOQzR5T1RJZ01qUTFMamMzUXpNeE5DNHhOVEVnTWpRMUxqSXpOaUF6TVRNdU5ETXhJREkwTlM0eE1qTWdNekV6TGpBek1TQXlORFV1TlRjeVRESTVOaTR5TmpFZ01qWTBMak00TmtNeU9UVXVPRGdnTWpZMExqZ3hNaUF5T1RZdU1EYzJJREkyTlM0ME16TWdNamsyTGpZeE9DQXlOalV1TlRFNFRETXdNUzQ0TmpRZ01qWTJMak0wTkVNek1ESXVNalU1SURJMk5pNDBNRGNnTXpBeUxqUTVOeUF5TmpZdU56Y3hJRE13TWk0ek9UVWdNalkzTGpFMU9Fd3lPVGd1TmpBeUlESTRNUzQxTWpaRE1qazRMalVnTWpneExqa3hNeUF5T1RndU56TTNJREk0TWk0eU56Y2dNams1TGpFek15QXlPREl1TXpNNVRETXdPQzQwTkRFZ01qZ3pMamd3TlVNek1EZ3VPRE0zSURJNE15NDROamNnTXpBNUxqSTBJREk0TXk0Mk1EUWdNekE1TGpNME15QXlPRE11TWpFM1RETXhNeTR4TXpZZ01qWTRMamcwT1VNek1UTXVNak00SURJMk9DNDBOaklnTXpFekxqWTBNU0F5TmpndU1UazVJRE14TkM0d016Y2dNalk0TGpJMk1Vd3pNVGt1TWpneUlESTJPUzR3T0RkYUlpQm1hV3hzUFNKaWJHRmpheUlnWm1sc2JDMXZjR0ZqYVhSNVBTSXdMalVpSUM4K1BIQmhkR2dnWkQwaVRUTXdNeTR4T0RRZ016TXdMakEyTWtNek1ETXVOekkySURNek1DNHhORGdnTXpBMExqSXlNU0F6TWprdU5qTTJJRE13TkM0d09EZ2dNekk1TGpFeU9Fd3lPVGd1TVRrMElETXdOaTQzTkRWRE1qazRMakExTXlBek1EWXVNakV4SURJNU55NHpNek1nTXpBMkxqQTVPQ0F5T1RZdU9UTXpJRE13Tmk0MU5EZE1Namd3TGpFMk15QXpNalV1TXpZeFF6STNPUzQzT0RJZ016STFMamM0TnlBeU56a3VPVGM1SURNeU5pNDBNRGdnTWpnd0xqVXlJRE15Tmk0ME9UTk1NamcxTGpjMk5pQXpNamN1TXpFNVF6STROaTR4TmpFZ016STNMak00TWlBeU9EWXVNems1SURNeU55NDNORFlnTWpnMkxqSTVOeUF6TWpndU1UTXpUREk0TWk0MU1EUWdNelF5TGpVd01VTXlPREl1TkRBeUlETTBNaTQ0T0RnZ01qZ3lMall6T1NBek5ETXVNalV5SURJNE15NHdNelVnTXpRekxqTXhORXd5T1RJdU16UTBJRE0wTkM0M09FTXlPVEl1TnpNNUlETTBOQzQ0TkRJZ01qa3pMakUwTWlBek5EUXVOVGM1SURJNU15NHlORFVnTXpRMExqRTVNa3d5T1RjdU1ETTRJRE15T1M0NE1qUkRNamszTGpFMElETXlPUzQwTXpjZ01qazNMalUwTXlBek1qa3VNVGMwSURJNU55NDVNemtnTXpJNUxqSXpOa3d6TURNdU1UZzBJRE16TUM0d05qSmFJaUJtYVd4c1BTSmliR0ZqYXlJZ1ptbHNiQzF2Y0dGamFYUjVQU0l3TGpVaUlDOCtQSEJoZEdnZ2MzUnliMnRsUFNKMWNtd29JMjFoYVc0cElpQnpkSEp2YTJVdGQybGtkR2c5SWpZaUlITjBjbTlyWlMxc2FXNWxZMkZ3UFNKeWIzVnVaQ0lnYzNSeWIydGxMV3hwYm1WcWIybHVQU0p5YjNWdVpDSWdaRDBpVFRJNU1DNHhNRGtnTkRZekxqUXhPRU15T1RJdU16VTRJRFExTkM0NU1ESWdNekF4TGpJek15QTBORGt1TVRFZ016QTVMamt6TXlBME5UQXVORGhNTnpjeExqQTNJRFV5TXk0d09UWkROemM1TGpjM0lEVXlOQzQwTmpjZ056ZzFJRFV6TWk0ME9DQTNPREl1TnpVeUlEVTBNQzQ1T1RaTU5qa3lMakE0TmlBNE9EUXVOREU0VERFNU9TNDBORE1nT0RBMkxqZzBUREk1TUM0eE1Ea2dORFl6TGpReE9Gb2lJR1pwYkd3OUltSnNZV05ySWlCbWFXeHNMVzl3WVdOcGRIazlJakF1TVRRaUlDOCtQSEJoZEdnZ1ptbHNiQzF5ZFd4bFBTSmxkbVZ1YjJSa0lpQmpiR2x3TFhKMWJHVTlJbVYyWlc1dlpHUWlJSE4wY205clpUMGlkWEpzS0NOdFlXbHVLU0lnYzNSeWIydGxMWGRwWkhSb1BTSTJJaUJ6ZEhKdmEyVXRiR2x1WldOaGNEMGljbTkxYm1RaUlITjBjbTlyWlMxc2FXNWxhbTlwYmowaWNtOTFibVFpSUdROUlrMDNPRGN1TlRnNUlESXpOeTR6TkRsTU5EWXdMak0xTkNBeE9EVXVPREU0VERRd05pNHpNalVnTXprd0xqUTJPVU0wTURNdU9EY3lJRE01T1M0M05Ua2dOREE1TGpVM09DQTBNRGd1TlRBeElEUXhPUzR3TmprZ05EQTVMams1Tmt3M01URXVPVE0wSURRMU5pNHhNVFJETnpJeExqUXlOU0EwTlRjdU5qQTVJRGN6TVM0eE1EY2dORFV4TGpJNUlEY3pNeTQxTmlBME5ESk1OemczTGpVNE9TQXlNemN1TXpRNVdrMDJOakF1TWpZNUlESTBOUzR3TVVNMk5UVXVOVEl6SURJME5DNHlOak1nTmpVd0xqWTRNaUF5TkRjdU5ESXpJRFkwT1M0ME5UWWdNalV5TGpBMk9FdzJNRGN1TXpnMklEUXhNUzQwTVRoRE5qQTJMakUySURReE5pNHdOak1nTmpBNUxqQXhNeUEwTWpBdU5ETTBJRFl4TXk0M05Ua2dOREl4TGpFNE1VdzJPREl1TkRrNUlEUXpNaTR3TURaRE5qZzNMakkwTlNBME16SXVOelV6SURZNU1pNHdPRFlnTkRJNUxqVTVOQ0EyT1RNdU16RXlJRFF5TkM0NU5EbE1Oek0xTGpNNE1pQXlOalV1TlRrNVF6Y3pOaTQyTURnZ01qWXdMamsxTkNBM016TXVOelUxSURJMU5pNDFPRE1nTnpJNUxqQXhJREkxTlM0NE16Vk1Oall3TGpJMk9TQXlORFV1TURGYUlpQm1hV3hzUFNKMWNtd29JMjFoYVc0cElpQXZQanh3WVhSb0lHWnBiR3d0Y25Wc1pUMGlaWFpsYm05a1pDSWdZMnhwY0MxeWRXeGxQU0psZG1WdWIyUmtJaUJrUFNKTk9EWTBMalkwTXlBeU9ETXVPVE0zUXpnMk5TNHhPRFlnTWpnekxqWXdOU0E0TmpVdU56QTRJREk0TkM0eU5UY2dPRFkxTGpJek9TQXlPRFF1TmpnelREZzBOQzR5TmpnZ016QXpMamN4T1VNNE5ETXVPVE00SURNd05DNHdNVGdnT0RRMExqQTVNeUF6TURRdU5URTNJRGcwTkM0MU1qWWdNekEwTGpVME9FdzROVE11TnpJMklETXdOUzR5TURkRE9EVTBMakU0TkNBek1EVXVNalFnT0RVMExqTXlNU0F6TURVdU56ZzNJRGcxTXk0NU5ESWdNekEyTGpBM01VdzRNek11T0RnMElETXlNUzR4TVRKRE9ETXpMalV3TmlBek1qRXVNemsySURnek15NDJORE1nTXpJeExqazBNeUE0TXpRdU1UQXhJRE15TVM0NU56Wk1PRFEwTGpBd055QXpNakl1TmpnMVF6ZzBOQzQwT1RFZ016SXlMamN5SURnME5DNDJNRFVnTXpJekxqTXhPU0E0TkRRdU1UYzNJRE15TXk0MU9FdzNPVGN1TnpVeUlETTFNUzQ1TlRSRE56azNMakl3T1NBek5USXVNamcySURjNU5pNDJPRGNnTXpVeExqWXpOQ0EzT1RjdU1UVTJJRE0xTVM0eU1EbE1PREU0TGpRd015QXpNekV1T1RJeVF6Z3hPQzQzTXpNZ016TXhMall5TWlBNE1UZ3VOVGMzSURNek1TNHhNak1nT0RFNExqRTBOU0F6TXpFdU1Ea3lURGd3T0M0M05EZ2dNek13TGpReVF6Z3dPQzR5T1RJZ016TXdMak00TnlBNE1EZ3VNVFUwSURNeU9TNDRORE1nT0RBNExqVXlPU0F6TWprdU5UVTRURGd5T0M0d05UUWdNekUwTGpjME5FTTRNamd1TkRNZ016RTBMalExT1NBNE1qZ3VNamt4SURNeE15NDVNVFVnT0RJM0xqZ3pOU0F6TVRNdU9EZ3lURGd4T0M0ek9Ea2dNekV6TGpJd05rTTRNVGN1T1RBMElETXhNeTR4TnpFZ09ERTNMamM1SURNeE1pNDFOeklnT0RFNExqSXhPQ0F6TVRJdU16RXhURGcyTkM0Mk5ETWdNamd6TGprek4xb2lJR1pwYkd3OUluZG9hWFJsSWlBdlBqeG5JSFJ5WVc1elptOXliVDBpYldGMGNtbDRLREF1T1RnM09ESTNJREF1TVRVMU5UVTNJQzB3TGpJMU5USTJNU0F3TGprMk5qZzNNaUF5TlRBZ056TTFLU0krUEhSbGVIUWdabTl1ZEMxbVlXMXBiSGs5SWtsdWRHVnlMQ0J6WVc1ekxYTmxjbWxtSWlCbWIyNTBMWGRsYVdkb2REMGlZbTlzWkNJZ1ptOXVkQzF6YVhwbFBTSTBNaUlnWm1sc2JEMGlJMFUxUlRkR09DSStUbVYzSUVGd2NDQk9ZVzFsUEM5MFpYaDBQangwWlhoMElHWnZiblF0Wm1GdGFXeDVQU0pKYm5SbGNpd2djMkZ1Y3kxelpYSnBaaUlnWm05dWRDMTNaV2xuYUhROUltNXZjbTFoYkNJZ2VUMGlOREFpSUdadmJuUXRjMmw2WlQwaU1qSWlJR1pwYkd3OUlpTTNSamd4T1RJaVBtNWxkeTFsYm5NdVpYUm9QQzkwWlhoMFBqd3ZaejQ4YVcxaFoyVWdkMmxrZEdnOUlqRTJOeUlnYUdWcFoyaDBQU0l4TmpjaUlIUnlZVzV6Wm05eWJUMGliV0YwY21sNEtEQXVPVGczT0RJM0lEQXVNVFUxTlRVM0lDMHdMakkxTlRJMk1TQXdMamsyTmpnM01pQTBORFF1TVRFM0lEVXlOQzR4TnlraUlHaHlaV1k5SW1SaGRHRTZhVzFoWjJVdmMzWm5LM2h0YkR0aVlYTmxOalFzVUVoT01scDVRakphV0VwNllWYzVkVkJUU1hoTWFrVnBTVWhvZEdKSE5YcFFVMHB2WkVoU2QwOXBPSFprTTJRelRHNWpla3h0T1hsYWVUaDVUVVJCZDB3elRqSmFlVWxuWlVjeGMySnVUVFpsUjNod1ltMXpPVWx0YURCa1NFRTJUSGs1TTJRelkzVmtlazExWWpOS2JreDZSVFZQVkd0MlpVZDRjR0p0YzJsSlNHYzVTV3BDZDJWRFNXZGxWREJwVFVoQ05FbHBRakpoVjFZelVXMDVORkJUU1hkSlJFRm5UVlJCZDAxRFFYaE5SRUYzU1dsQ2JHSnRSbWxpUjFWMFdXMUdhbUV5WkhsaU0xWjFXa1F3YVdKdFZqTkpSRUZuVFVOQmVFMUVRWGRKUkVWM1RVUkJhVWxJYUhSaVJIQjZZMGRHYWxwVU1HbGpTRXBzWXpKV2VXUnRWV2xRWjI4NFdubzBPR05IUmpCaFEwSnJVRk5LVGs1VVFYZE1SRVYzVVhwSmVVOVROREJNUkVWM1RFUkZkMHhFU1hsUFV6UXdURVJGZDB4RVZYZE5SMDEzVEVSSk0wMUROREpNUkVsNFQxTTBNRXhFVVRWTlEzY3dUMVJCYzA1RWEzZFpla2t6VFVNME1reEVRWE5PUkd0M1RGUkplRTlUTkRCTVJGRTFUVU13TUU5VVFrUlBWR3QzVEVSSmVVOVROREJNUkdNelRVTTBNa3hFUlhkTVJGVjNUVU4zZUUxSWIyZFVWR2Q0VGxOM05FMVVWbXBNVkZGM1RHcHJjMDVFUVhWUFV6QTBUME0wTWt4RVkzcE1ha1YwVFZSUmVFeHFXWE5QVkZWMVRsZE5kRTVVVVhWUFUzZDVUWGswZVV4VVJYaE5lVFI1VEVSTk1VeFVSVE5OZVRRd1RFUk5NVmw1TURKTlF6UjVURVJCZEUxVVJUUk1hbFYwVFZSRmRVOURNSGhPZWsxMVRrTXdlazVWVFhsT2VrMTFUbWwzTkU5RVozTk5ha2t4VEdwcmMwOUVWVEZNYW10elRWUm5NVXhFWjNoT1dFMTBUbnBOZEU5RVozVk9hVEExVGxNME1VeFVSVEJOVXpReVdYa3dlVTE1TkhsTVZGVXdUR3ByZEUxNlZYUk5WRVY2VEdwSmRFMTZWWFJOVkdONlRHcFNhazFETURKTlF6UjVURVJGZUV4cVozUk5WRVUwVEdwVmMwMTZWWFJOVkdONlRHcFNhazFxU1hWT1F6QXhUWGwzTVU1RE5ESk1WRVYzVFVNME0weEVhekZNYWxWMFRWUlJlRXhxV25wUFJHZDFUbWt3TTAxNWQzaE9SRVYxVG1rd05VNVROREZaZWxVd1RHcHJkRTFxVFhWTmFYZDRUVlJOZFUxcE1IcE9VM2Q0VG5wTmRVNURNSHBPVjAweVRVTTBlVXhFUVhOTlZFVTBUR3BWYzAxVVJYVlBRM2Q0VG5wTmRVNURkM3BPVjAweFRYbDNlVTFwTkRCTVJFVjNUVU0wTTB4RVZUQk1hbGx6VFZSUmVFeHFXWE5QVkZWMVRsZE5NRTFETkRWTVJGRjNUR3ByYzA1NlRYTlBSR2QxVG1sM05VNVROREZNUkVVd1RWTTBNbGw2U1hwTWFrbHpUbFJSZFU5VGQzcE9VM2Q0VFZSTmRVMXBkM3BPVTNkNFRucE5kVTVIVFhkTVJGbDNUR3BKZEUxVVJYVlBRM2Q0VFZSbmRVNVRNSHBPVTNkNFRucE5kVTVGVFRSUFJHZHpUbnBKTWt4cVVYTlBSRlV4VEdwcmMwNTZZekJNYWtWelQwUkZNVXhFWjNoT1dHOXBUSG8wT0V3eVl5dERhbmQyWXpOYWJsQm5QVDBpSUM4K1BHUmxabk0rUEdacGJIUmxjaUJwWkQwaVpHbHphMlYwZEdVdGMyaGhaRzkzSWlCNFBTSTNNQzQzTkRnNUlpQjVQU0l4T1RVdU56RXlJaUIzYVdSMGFEMGlPVFUxTGpjek15SWdhR1ZwWjJoMFBTSTRNekl1TlRVNElpQm1hV3gwWlhKVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR052Ykc5eUxXbHVkR1Z5Y0c5c1lYUnBiMjR0Wm1sc2RHVnljejBpYzFKSFFpSStQR1psUm14dmIyUWdabXh2YjJRdGIzQmhZMmwwZVQwaU1DSWdMejQ4Wm1WQ2JHVnVaQ0JwYmowaVUyOTFjbU5sUjNKaGNHaHBZeUlnTHo0OFptVkhZWFZ6YzJsaGJrSnNkWElnYzNSa1JHVjJhV0YwYVc5dVBTSTBNaUlnTHo0OEwyWnBiSFJsY2o0OGJHbHVaV0Z5UjNKaFpHbGxiblFnYVdROUltSmhZMnRuY205MWJtUWlJSGd4UFNJMU16SXVOU0lnZVRFOUlqQWlJSGd5UFNJMU16SXVOU0lnZVRJOUlqRXdOalVpSUdkeVlXUnBaVzUwVlc1cGRITTlJblZ6WlhKVGNHRmpaVTl1VlhObElqNDhjM1J2Y0NBdlBqeHpkRzl3SUc5bVpuTmxkRDBpTVNJZ2MzUnZjQzFqYjJ4dmNqMGlJekV6TVRNeE15SWdMejQ4TDJ4cGJtVmhja2R5WVdScFpXNTBQanh5WVdScFlXeEhjbUZrYVdWdWRDQnBaRDBpWW1GamEyZHliM1Z1WkMxeVlXUnBZV3dpSUdONFBTSXdJaUJqZVQwaU1DSWdjajBpTVNJZ1ozSmhaR2xsYm5SVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR2R5WVdScFpXNTBWSEpoYm5ObWIzSnRQU0owY21GdWMyeGhkR1VvTlRNeUxqVWdOVE15TGpVcElISnZkR0YwWlNnNE9TNDVOakVwSUhOallXeGxLRGN6TlNraVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTTJOVFF6TWpFaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTmpVME16SXhJaUJ6ZEc5d0xXOXdZV05wZEhrOUlqQWlJQzgrUEM5eVlXUnBZV3hIY21Ga2FXVnVkRDQ4YkdsdVpXRnlSM0poWkdsbGJuUWdhV1E5SW1ScGMydGxkSFJsTFdkeVlXUnBaVzUwSWlCNE1UMGlPVEkxTGpZeU5pSWdlVEU5SWpJMU5pNDRPVFlpSUhneVBTSXhNell1TnpjNUlpQjVNajBpT0RBd0xqSXdNeUlnWjNKaFpHbGxiblJWYm1sMGN6MGlkWE5sY2xOd1lXTmxUMjVWYzJVaVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTTJOVFF6TWpFaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTWtNek1UTkdJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEd4cGJtVmhja2R5WVdScFpXNTBJR2xrUFNKdFlXbHVJajQ4YzNSdmNDQnpkRzl3TFdOdmJHOXlQU0lqTmpVME16SXhJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEM5a1pXWnpQand2YzNablBnPT0iLCJhY2Nlc3NfcG9pbnRfYXV0b19hcHByb3ZhbCI6ZmFsc2UsInZlcmlmaWVkIjpmYWxzZSwiYXR0cmlidXRlcyI6IFt7InRyYWl0X3R5cGUiOiAiRU5TIiwgInZhbHVlIjoibmV3LWVucy5ldGgifSx7InRyYWl0X3R5cGUiOiAiQ29tbWl0IEhhc2giLCAidmFsdWUiOiJjZTFhM2ZjMTQxZTI5ZjhlMWQwMGE2NTRlMTU2YzQ5ODJkNzcxMWJmIn0seyJ0cmFpdF90eXBlIjogIlJlcG9zaXRvcnkiLCAidmFsdWUiOiJodHRwczovL2dpdGh1Yi5jb20vb3RoZXIvcmVwbyJ9LHsidHJhaXRfdHlwZSI6ICJWZXJzaW9uIiwgInZhbHVlIjoiMSJ9LHsidHJhaXRfdHlwZSI6ICJDb2xvciIsICJ2YWx1ZSI6IiM2NTQzMjEifV19"; } diff --git a/contracts/test/foundry/FleekERC721/ENS.t.sol b/contracts/test/foundry/FleekERC721/ENS.t.sol new file mode 100644 index 0000000..280d929 --- /dev/null +++ b/contracts/test/foundry/FleekERC721/ENS.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.17; + +import "./TestBase.sol"; +import {Utils} from "./Utils.sol"; + +contract Test_FleekERC721_ENS is Test_FleekERC721_Base { + function expectRevertWithMustBeENSOwner() internal { + vm.expectRevert(MustBeENSOwner.selector); + } + + function setUp() public { + baseSetUp(); + } + + function testFuzz_cannotMintIfNotENSOwner(address account) public { + vm.assume(deployer != account); + vm.prank(account); + expectRevertWithMustBeENSOwner(); + mintDefault(account); + } + + function testFuzz_cannotSetTokenENSIfNotENSOwner(address account) public { + vm.assume(deployer != account); + mintDefault(account); + + vm.prank(account); + expectRevertWithMustBeENSOwner(); + CuT.setTokenENS(0, TestConstants.APP_ENS); + } +} diff --git a/contracts/test/foundry/FleekERC721/GetToken.t.sol b/contracts/test/foundry/FleekERC721/GetToken.t.sol index 4cd2234..dfcce32 100644 --- a/contracts/test/foundry/FleekERC721/GetToken.t.sol +++ b/contracts/test/foundry/FleekERC721/GetToken.t.sol @@ -18,7 +18,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base { string memory name, string memory description, string memory externalURL, - string memory ENS, + string memory ens, uint256 currentBuild, string memory logo, uint24 color @@ -28,7 +28,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base { assertEq(externalURL, TestConstants.APP_EXTERNAL_URL); assertEq(logo, TestConstants.LOGO_0); assertEq(color, TestConstants.APP_COLOR); - assertEq(ENS, TestConstants.APP_ENS); + assertEq(ens, TestConstants.APP_ENS); assertEq(currentBuild, 0); } @@ -45,6 +45,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base { CuT.setTokenName(tokenId, newAppName); CuT.setTokenDescription(tokenId, newDescription); CuT.setTokenExternalURL(tokenId, newExternalURL); + transferENS(newENS, deployer); CuT.setTokenENS(tokenId, newENS); CuT.setTokenBuild(tokenId, newCommitHash, newRepository); CuT.setTokenLogoAndColor(tokenId, newLogo, newColor); @@ -53,7 +54,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base { string memory name, string memory description, string memory externalURL, - string memory ENS, + string memory ens, uint256 currentBuild, string memory logo, uint24 color @@ -63,7 +64,7 @@ contract Test_FleekERC721_GetToken is Test_FleekERC721_Base { assertEq(externalURL, newExternalURL); assertEq(logo, newLogo); assertEq(color, newColor); - assertEq(ENS, newENS); + assertEq(ens, newENS); assertEq(currentBuild, 1); } diff --git a/contracts/test/foundry/FleekERC721/Mint.t.sol b/contracts/test/foundry/FleekERC721/Mint.t.sol index 01e94e9..e66d637 100644 --- a/contracts/test/foundry/FleekERC721/Mint.t.sol +++ b/contracts/test/foundry/FleekERC721/Mint.t.sol @@ -26,6 +26,8 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base { function test_mintTwoTokensForTwoAddresses() public { uint256 firstMint = mintDefault(deployer); + + transferENS("fleek.eth", deployer); uint256 secondMint = CuT.mint( address(12), "Different App Name", @@ -45,6 +47,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base { } function test_mintWithAutoApprovalAPsOn() public { + transferENS("fleek.eth", deployer); uint256 mint = CuT.mint( address(12), "Different App Name", @@ -83,6 +86,7 @@ contract Test_FleekERC721_Mint is Test_FleekERC721_Base { bool autoApprovalAp ) public { vm.assume(to != address(0)); + transferENS(ens, deployer); uint256 tokenId = CuT.mint( to, appName, diff --git a/contracts/test/foundry/FleekERC721/TestBase.sol b/contracts/test/foundry/FleekERC721/TestBase.sol index 3fa55aa..27cb5d3 100644 --- a/contracts/test/foundry/FleekERC721/TestBase.sol +++ b/contracts/test/foundry/FleekERC721/TestBase.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.17; import "forge-std/Test.sol"; import "contracts/FleekERC721.sol"; import {TestConstants} from "./Constants.sol"; +import {Utils} from "./Utils.sol"; abstract contract Test_FleekERC721_Assertions is Test { function expectRevertWithTokenRole(uint256 tokenId, FleekAccessControl.TokenRoles role) public { @@ -47,6 +48,7 @@ abstract contract Test_FleekERC721_Assertions is Test { abstract contract Test_FleekERC721_Base is Test, Test_FleekERC721_Assertions { FleekERC721 internal CuT; // Contract Under Test address internal deployer; + ENS internal constant _ens = ENS(0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e); function deployUninitialized() internal returns (FleekERC721) { FleekERC721 _contract = new FleekERC721(); @@ -59,6 +61,15 @@ abstract contract Test_FleekERC721_Base is Test, Test_FleekERC721_Assertions { CuT = deployUninitialized(); CuT.initialize("Test Contract", "FLKAPS", new uint256[](0)); deployer = address(this); + transferENS(TestConstants.APP_ENS, deployer); + } + + function transferENS(string memory ens, address newOwner) public { + bytes32 node = Utils.namehash(ens); + address ensOwner = _ens.owner(node); + vm.deal(ensOwner, 100000000000); + vm.prank(ensOwner); + _ens.setOwner(node, newOwner); } function mintDefault(address to) internal returns (uint256) { diff --git a/contracts/test/foundry/FleekERC721/TokenURI.t.sol b/contracts/test/foundry/FleekERC721/TokenURI.t.sol index a44b402..8204502 100644 --- a/contracts/test/foundry/FleekERC721/TokenURI.t.sol +++ b/contracts/test/foundry/FleekERC721/TokenURI.t.sol @@ -47,7 +47,7 @@ contract Test_FleekERC721_TokenURI is Test_FleekERC721_Base, Test_FleekERC721_To string memory uri = CuT.tokenURI(tokenId); assertEq( uri, - "data:application/json;base64,eyJuYW1lIjoiRm91bmRyeSBUZXN0IEFwcCIsImRlc2NyaXB0aW9uIjoiVGhpcyBpcyBhIHRlc3QgYXBwbGljYXRpb24gc3VibWl0dGVkIGJ5IGZvdW5kcnkgdGVzdHMuIiwib3duZXIiOiIweDM0YTFkM2ZmZjM5NTg4NDNjNDNhZDgwZjMwYjk0YzUxMDY0NWMzMTYiLCJleHRlcm5hbF91cmwiOiJodHRwczovL2ZvdW5kcnkudGVzdCIsImltYWdlIjoiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCM2FXUjBhRDBpTVRBMk5TSWdhR1ZwWjJoMFBTSXhNRFkxSWlCMmFXVjNRbTk0UFNJd0lEQWdNVEEyTlNBeE1EWTFJaUJtYVd4c1BTSnViMjVsSWlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhodGJHNXpPbmhzYVc1clBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1TDNoc2FXNXJJajQ4YzNSNWJHVWdkSGx3WlQwaWRHVjRkQzlqYzNNaVBrQnBiWEJ2Y25RZ2RYSnNLQ0pvZEhSd2N6b3ZMMlp2Ym5SekxtZHZiMmRzWldGd2FYTXVZMjl0TDJOemN6SS9abUZ0YVd4NVBVbHVkR1Z5T25kbmFIUkFOVEF3T3pZd01DSXBPend2YzNSNWJHVStQSEpsWTNRZ2QybGtkR2c5SWpFd05qVWlJR2hsYVdkb2REMGlNVEEyTlNJZ1ptbHNiRDBpZFhKc0tDTmlZV05yWjNKdmRXNWtLU0lnTHo0OGNtVmpkQ0J2Y0dGamFYUjVQU0l3TGpJaUlIZHBaSFJvUFNJeE1EWTFJaUJvWldsbmFIUTlJakV3TmpVaUlHWnBiR3c5SW5WeWJDZ2pZbUZqYTJkeWIzVnVaQzF5WVdScFlXd3BJaUF2UGp4bklHWnBiSFJsY2owaWRYSnNLQ05rYVhOclpYUjBaUzF6YUdGa2IzY3BJajQ4Y0dGMGFDQmtQU0pOT0RVM0xqSXpNU0F5TnprdU56RXlURGt3TWk0eU5DQXlPRFl1TmpjMVF6a3hNQzQxTkRjZ01qZzNMamsySURreE55NDVNVFVnTWpreUxqY3lNU0E1TWpJdU5TQXlPVGt1TnpZNFREa3pPQzQ0T1RRZ016STBMamsyTkVNNU5ESXVNalE1SURNek1DNHhNaUE1TkRNdU16RXhJRE16Tmk0ME16Y2dPVFF4TGpneU55QXpOREl1TkRBMlREa3pOeTQzT1RnZ016VTRMall4TlV3NU1qUXVNRFE1SURNMU5pNDJOVXc1TVRrdU5ERTJJRE0zTkM0d09EUk1PVE0wTGpBMk9DQXpOell1TWpSTU56a3hMamswTnlBNU1qSXVNVFV5UXpjNE9DNHhNRGtnT1RNMkxqZzVOaUEzTnpNdU5qazBJRGswTmk0ek1EZ2dOelU0TGpZMU1TQTVORE11T0RrelRERTNPUzQyTXpZZ09EVXdMamt5T0VNeE5qSXVNekU0SURnME9DNHhORGNnTVRVeExqSXhOU0E0TXpBdU9UZzNJREUxTlM0M056WWdPREUwTGpBMU1Vd3hOakF1TkRjNElEYzVOaTQxT1V3M01EUXVNekUxSURnM09TNDFOelJNT0RVM0xqSXpNU0F5TnprdU56RXlXaUlnWm1sc2JEMGlJekExTURVd05TSWdMejQ4TDJjK1BIQmhkR2dnWkQwaVRUZzBNQzR5TXpFZ01qUXdMamN4TWt3NE9EVXVNalFnTWpRM0xqWTNOVU00T1RNdU5UUTNJREkwT0M0NU5qRWdPVEF3TGpreE5TQXlOVE11TnpJeUlEa3dOUzQxSURJMk1DNDNOamhNT1RJeExqZzVOQ0F5T0RVdU9UWTFRemt5TlM0eU5Ea2dNamt4TGpFeUlEa3lOaTR6TVRFZ01qazNMalF6TnlBNU1qUXVPREkzSURNd015NDBNRFpNT1RJd0xqYzVPQ0F6TVRrdU5qRTJURGt3Tnk0d05Ea2dNekUzTGpZMVREa3dNaTQwTVRZZ016TTFMakE0TkV3NU1UY3VNRFk0SURNek55NHlOREZNTnpjMExqazBOeUE0T0RNdU1UVXlRemMzTVM0eE1Ea2dPRGszTGpnNU5pQTNOVFl1TmprMElEa3dOeTR6TURnZ056UXhMalkxTVNBNU1EUXVPRGt6VERFMk1pNDJNellnT0RFeExqa3lPRU14TkRVdU16RTRJRGd3T1M0eE5EY2dNVE0wTGpJeE5TQTNPVEV1T1RnM0lERXpPQzQzTnpZZ056YzFMakExTVV3eE5ETXVORGM0SURjMU55NDFPVXcyT0RjdU16RTFJRGcwTUM0MU56Uk1PRFF3TGpJek1TQXlOREF1TnpFeVdpSWdabWxzYkQwaWRYSnNLQ050WVdsdUtTSWdMejQ4Y0dGMGFDQm1hV3hzTFhKMWJHVTlJbVYyWlc1dlpHUWlJR05zYVhBdGNuVnNaVDBpWlhabGJtOWtaQ0lnWkQwaVRUTXhPUzQ0TkRjZ01UWXhMalV3TWtNek1UQXVNelUySURFMk1DNHdNRGNnTXpBd0xqWTNOQ0F4TmpZdU16STJJREk1T0M0eU1qRWdNVGMxTGpZeE5rd3hNemd1TnpJMElEYzNPUzQzTlRoRE1UTTJMakkzTVNBM09Ea3VNRFE0SURFME1TNDVOemNnTnprM0xqYzVJREUxTVM0ME5qZ2dOems1TGpJNE5VdzNOREF1TURZeElEZzVNUzQ1TnpORE56UTVMalUxTXlBNE9UTXVORFkzSURjMU9TNHlNelVnT0RnM0xqRTBPQ0EzTmpFdU5qZzNJRGczTnk0NE5UaE1PVEF5TGpRd05TQXpORFF1T0RVMFREZzRPUzR4TlRnZ016UXlMamMyT0V3NE9UZ3VPRGN5SURNd05TNDVOekpNT1RFeUxqRXhPU0F6TURndU1EVTVURGt4TXk0M016TWdNekF4TGprME5rTTVNVFF1T0RNM0lESTVOeTQzTmpJZ09URTBMak13T1NBeU9UTXVORGMySURreE1pNHlOVEVnTWpnNUxqa3lOMHc0T1RNdU5EZzBJREkxTnk0MU5qbERPRGt4TGpFMU15QXlOVE11TlRRNUlEZzROeTR3TmpNZ01qVXdMamd5TXlBNE9ESXVNakl4SURJMU1DNHdOakZNT0RJNExqSXdOU0F5TkRFdU5UVTBRemd5TWk0eU1qUWdNalF3TGpZeE15QTRNVFV1T0RZNUlESTBNaTQzT0RNZ09ERXhMalF5TnlBeU5EY3VNamcwVERnd05TNDJPRFlnTWpVekxqRXdNME00TURRdU1qQTFJREkxTkM0Mk1ETWdPREF5TGpBNE55QXlOVFV1TXpJMklEZ3dNQzR3T1RNZ01qVTFMakF4TTB3M09ETXVOakV4SURJMU1pNDBNVGRNTnpNMExqTWdORE01TGpFNU5rTTNNekV1TkRNNUlEUTFNQzR3TXpVZ056SXdMakUwTXlBME5UY3VOREEzSURjd09TNHdOeUEwTlRVdU5qWXpURE15T0M0NE5EY2dNemsxTGpjNE9FTXpNVGN1TnpjMElETTVOQzR3TkRVZ016RXhMakV4TnlBek9ETXVPRFExSURNeE15NDVOemdnTXpjekxqQXdOMHd6TmpZdU5USTRJREUzTXk0NU5qSk1NelkyTGpVek15QXhOek11T1RReFF6TTJOeTR5TXpRZ01UY3hMakkwSURNMk5TNDFOeklnTVRZNExqY3dNaUF6TmpJdU9ERWdNVFk0TGpJMk4wd3pNVGt1T0RRM0lERTJNUzQxTURKYVRUTTJPUzR6T1RJZ01UYzBMalF4TkV3ek5qZ3VOalV5SURFM055NHlNVGRNTXpFMkxqZzBNeUF6TnpNdU5EVTRRek14TkM0ek9TQXpPREl1TnpRNElETXlNQzR3T1RZZ016a3hMalE1SURNeU9TNDFPRGNnTXpreUxqazROVXczTURrdU9ERWdORFV5TGpnMlF6Y3hPUzR6TURFZ05EVTBMak0xTkNBM01qZ3VPVGd6SURRME9DNHdNelVnTnpNeExqUXpOaUEwTXpndU56UTFURGM0TUM0M05EY2dNalV4TGprMk5rdzNPRE11TWpRMUlESTBNaTQxTURSTU56Z3pMams0TlNBeU16a3VOekF4VERNMk9TNHpPVElnTVRjMExqUXhORm9pSUdacGJHdzlJaU14TXpFek1UWWlJQzgrUEhCaGRHZ2dabWxzYkMxeWRXeGxQU0psZG1WdWIyUmtJaUJqYkdsd0xYSjFiR1U5SW1WMlpXNXZaR1FpSUhOMGNtOXJaVDBpZFhKc0tDTnRZV2x1S1NJZ2MzUnliMnRsTFhkcFpIUm9QU0kwSWlCemRISnZhMlV0YkdsdVpXTmhjRDBpY205MWJtUWlJSE4wY205clpTMXNhVzVsYW05cGJqMGljbTkxYm1RaUlHUTlJazB6TVRrdU9EUTNJREUyTVM0MU1ESkRNekV3TGpNMU5pQXhOakF1TURBM0lETXdNQzQyTnpRZ01UWTJMak15TmlBeU9UZ3VNakl4SURFM05TNDJNVFpNTVRNNExqY3lOQ0EzTnprdU56VTRRekV6Tmk0eU56RWdOemc1TGpBME9DQXhOREV1T1RjM0lEYzVOeTQzT1NBeE5URXVORFk0SURjNU9TNHlPRFZNTnpRd0xqQTJNU0E0T1RFdU9UY3pRemMwT1M0MU5UTWdPRGt6TGpRMk55QTNOVGt1TWpNMUlEZzROeTR4TkRnZ056WXhMalk0TnlBNE56Y3VPRFU0VERrd01pNDBNRFVnTXpRMExqZzFORXc0T0RrdU1UVTRJRE0wTWk0M05qaE1PRGs0TGpnM01pQXpNRFV1T1RjeVREa3hNaTR4TVRrZ016QTRMakExT1V3NU1UTXVOek16SURNd01TNDVORFpET1RFMExqZ3pOeUF5T1RjdU56WXlJRGt4TkM0ek1Ea2dNamt6TGpRM05pQTVNVEl1TWpVeElESTRPUzQ1TWpkTU9Ea3pMalE0TkNBeU5UY3VOVFk1UXpnNU1TNHhOVE1nTWpVekxqVTBPU0E0T0RjdU1EWXpJREkxTUM0NE1qTWdPRGd5TGpJeU1TQXlOVEF1TURZeFREZ3lPQzR5TURVZ01qUXhMalUxTkVNNE1qSXVNakkwSURJME1DNDJNVE1nT0RFMUxqZzJPU0F5TkRJdU56Z3pJRGd4TVM0ME1qY2dNalEzTGpJNE5FdzRNRFV1TmpnMklESTFNeTR4TURORE9EQTBMakl3TlNBeU5UUXVOakF6SURnd01pNHdPRGNnTWpVMUxqTXlOaUE0TURBdU1Ea3pJREkxTlM0d01UTk1Oemd6TGpZeE1TQXlOVEl1TkRFM1REY3pOQzR6SURRek9TNHhPVFpETnpNeExqUXpPU0EwTlRBdU1ETTFJRGN5TUM0eE5ETWdORFUzTGpRd055QTNNRGt1TURjZ05EVTFMalkyTTB3ek1qZ3VPRFEzSURNNU5TNDNPRGhETXpFM0xqYzNOQ0F6T1RRdU1EUTFJRE14TVM0eE1UY2dNemd6TGpnME5TQXpNVE11T1RjNElETTNNeTR3TURkTU16WTJMalV5T0NBeE56TXVPVFl5VERNMk5pNDFNek1nTVRjekxqazBNVU16TmpjdU1qTTBJREUzTVM0eU5DQXpOalV1TlRjeUlERTJPQzQzTURJZ016WXlMamd4SURFMk9DNHlOamRNTXpFNUxqZzBOeUF4TmpFdU5UQXlXazB6TmprdU16a3lJREUzTkM0ME1UUk1Nelk0TGpZMU1pQXhOemN1TWpFM1RETXhOaTQ0TkRNZ016Y3pMalExT0VNek1UUXVNemtnTXpneUxqYzBPQ0F6TWpBdU1EazJJRE01TVM0ME9TQXpNamt1TlRnM0lETTVNaTQ1T0RWTU56QTVMamd4SURRMU1pNDROa00zTVRrdU16QXhJRFExTkM0ek5UUWdOekk0TGprNE15QTBORGd1TURNMUlEY3pNUzQwTXpZZ05ETTRMamMwTlV3M09EQXVOelEzSURJMU1TNDVOalpNTnpnekxqSTBOU0F5TkRJdU5UQTBURGM0TXk0NU9EVWdNak01TGpjd01Vd3pOamt1TXpreUlERTNOQzQwTVRSYUlpQm1hV3hzUFNKMWNtd29JMlJwYzJ0bGRIUmxMV2R5WVdScFpXNTBLU0lnWm1sc2JDMXZjR0ZqYVhSNVBTSXdMaklpSUM4K1BIQmhkR2dnWkQwaVRUTXpOUzR6T0NBeU1EZ3VNVEV6UXpNek5TNDVNaklnTWpBNExqRTVPQ0F6TXpZdU5ERTNJREl3Tnk0Mk9EWWdNek0yTGpJNE15QXlNRGN1TVRjNVRETXpNQzR6T1NBeE9EUXVOemsxUXpNek1DNHlORGtnTVRnMExqSTJNU0F6TWprdU5USTVJREU0TkM0eE5EZ2dNekk1TGpFeU9TQXhPRFF1TlRrM1RETXhNaTR6TlRnZ01qQXpMalF4TVVNek1URXVPVGM0SURJd015NDRNemdnTXpFeUxqRTNOQ0F5TURRdU5EVTRJRE14TWk0M01UWWdNakEwTGpVME5Fd3pNVGN1T1RZeUlESXdOUzR6TjBNek1UZ3VNelUzSURJd05TNDBNeklnTXpFNExqVTVOU0F5TURVdU56azJJRE14T0M0ME9UTWdNakEyTGpFNE0wd3pNVFF1TnlBeU1qQXVOVFV4UXpNeE5DNDFPVGNnTWpJd0xqa3pPQ0F6TVRRdU9ETTFJREl5TVM0ek1ESWdNekUxTGpJek1TQXlNakV1TXpZMFRETXlOQzQxTXprZ01qSXlMamd6UXpNeU5DNDVNelVnTWpJeUxqZzVNeUF6TWpVdU16TTRJREl5TWk0Mk1qa2dNekkxTGpRMElESXlNaTR5TkRKTU16STVMakl6TXlBeU1EY3VPRGMxUXpNeU9TNHpNellnTWpBM0xqUTRPQ0F6TWprdU56TTVJREl3Tnk0eU1qUWdNek13TGpFek5TQXlNRGN1TWpnMlRETXpOUzR6T0NBeU1EZ3VNVEV6V2lJZ1ptbHNiRDBpZFhKc0tDTnRZV2x1S1NJZ0x6NDhjR0YwYUNCa1BTSk5NekU1TGpJNE1pQXlOamt1TURnM1F6TXhPUzQ0TWpRZ01qWTVMakUzTXlBek1qQXVNekU1SURJMk9DNDJOakVnTXpJd0xqRTROaUF5TmpndU1UVTBURE14TkM0eU9USWdNalExTGpjM1F6TXhOQzR4TlRFZ01qUTFMakl6TmlBek1UTXVORE14SURJME5TNHhNak1nTXpFekxqQXpNU0F5TkRVdU5UY3lUREk1Tmk0eU5qRWdNalkwTGpNNE5rTXlPVFV1T0RnZ01qWTBMamd4TWlBeU9UWXVNRGMySURJMk5TNDBNek1nTWprMkxqWXhPQ0F5TmpVdU5URTRURE13TVM0NE5qUWdNalkyTGpNME5FTXpNREl1TWpVNUlESTJOaTQwTURjZ016QXlMalE1TnlBeU5qWXVOemN4SURNd01pNHpPVFVnTWpZM0xqRTFPRXd5T1RndU5qQXlJREk0TVM0MU1qWkRNams0TGpVZ01qZ3hMamt4TXlBeU9UZ3VOek0zSURJNE1pNHlOemNnTWprNUxqRXpNeUF5T0RJdU16TTVURE13T0M0ME5ERWdNamd6TGpnd05VTXpNRGd1T0RNM0lESTRNeTQ0TmpjZ016QTVMakkwSURJNE15NDJNRFFnTXpBNUxqTTBNeUF5T0RNdU1qRTNURE14TXk0eE16WWdNalk0TGpnME9VTXpNVE11TWpNNElESTJPQzQwTmpJZ016RXpMalkwTVNBeU5qZ3VNVGs1SURNeE5DNHdNemNnTWpZNExqSTJNVXd6TVRrdU1qZ3lJREkyT1M0d09EZGFJaUJtYVd4c1BTSmliR0ZqYXlJZ1ptbHNiQzF2Y0dGamFYUjVQU0l3TGpVaUlDOCtQSEJoZEdnZ1pEMGlUVE13TXk0eE9EUWdNek13TGpBMk1rTXpNRE11TnpJMklETXpNQzR4TkRnZ016QTBMakl5TVNBek1qa3VOak0ySURNd05DNHdPRGdnTXpJNUxqRXlPRXd5T1RndU1UazBJRE13Tmk0M05EVkRNams0TGpBMU15QXpNRFl1TWpFeElESTVOeTR6TXpNZ016QTJMakE1T0NBeU9UWXVPVE16SURNd05pNDFORGRNTWpnd0xqRTJNeUF6TWpVdU16WXhRekkzT1M0M09ESWdNekkxTGpjNE55QXlOemt1T1RjNUlETXlOaTQwTURnZ01qZ3dMalV5SURNeU5pNDBPVE5NTWpnMUxqYzJOaUF6TWpjdU16RTVRekk0Tmk0eE5qRWdNekkzTGpNNE1pQXlPRFl1TXprNUlETXlOeTQzTkRZZ01qZzJMakk1TnlBek1qZ3VNVE16VERJNE1pNDFNRFFnTXpReUxqVXdNVU15T0RJdU5EQXlJRE0wTWk0NE9EZ2dNamd5TGpZek9TQXpORE11TWpVeUlESTRNeTR3TXpVZ016UXpMak14TkV3eU9USXVNelEwSURNME5DNDNPRU15T1RJdU56TTVJRE0wTkM0NE5ESWdNamt6TGpFME1pQXpORFF1TlRjNUlESTVNeTR5TkRVZ016UTBMakU1TWt3eU9UY3VNRE00SURNeU9TNDRNalJETWprM0xqRTBJRE15T1M0ME16Y2dNamszTGpVME15QXpNamt1TVRjMElESTVOeTQ1TXprZ016STVMakl6Tmt3ek1ETXVNVGcwSURNek1DNHdOakphSWlCbWFXeHNQU0ppYkdGamF5SWdabWxzYkMxdmNHRmphWFI1UFNJd0xqVWlJQzgrUEhCaGRHZ2djM1J5YjJ0bFBTSjFjbXdvSTIxaGFXNHBJaUJ6ZEhKdmEyVXRkMmxrZEdnOUlqWWlJSE4wY205clpTMXNhVzVsWTJGd1BTSnliM1Z1WkNJZ2MzUnliMnRsTFd4cGJtVnFiMmx1UFNKeWIzVnVaQ0lnWkQwaVRUSTVNQzR4TURrZ05EWXpMalF4T0VNeU9USXVNelU0SURRMU5DNDVNRElnTXpBeExqSXpNeUEwTkRrdU1URWdNekE1TGprek15QTBOVEF1TkRoTU56Y3hMakEzSURVeU15NHdPVFpETnpjNUxqYzNJRFV5TkM0ME5qY2dOemcxSURVek1pNDBPQ0EzT0RJdU56VXlJRFUwTUM0NU9UWk1Oamt5TGpBNE5pQTRPRFF1TkRFNFRERTVPUzQwTkRNZ09EQTJMamcwVERJNU1DNHhNRGtnTkRZekxqUXhPRm9pSUdacGJHdzlJbUpzWVdOcklpQm1hV3hzTFc5d1lXTnBkSGs5SWpBdU1UUWlJQzgrUEhCaGRHZ2dabWxzYkMxeWRXeGxQU0psZG1WdWIyUmtJaUJqYkdsd0xYSjFiR1U5SW1WMlpXNXZaR1FpSUhOMGNtOXJaVDBpZFhKc0tDTnRZV2x1S1NJZ2MzUnliMnRsTFhkcFpIUm9QU0kySWlCemRISnZhMlV0YkdsdVpXTmhjRDBpY205MWJtUWlJSE4wY205clpTMXNhVzVsYW05cGJqMGljbTkxYm1RaUlHUTlJazAzT0RjdU5UZzVJREl6Tnk0ek5EbE1ORFl3TGpNMU5DQXhPRFV1T0RFNFREUXdOaTR6TWpVZ016a3dMalEyT1VNME1ETXVPRGN5SURNNU9TNDNOVGtnTkRBNUxqVTNPQ0EwTURndU5UQXhJRFF4T1M0d05qa2dOREE1TGprNU5rdzNNVEV1T1RNMElEUTFOaTR4TVRSRE56SXhMalF5TlNBME5UY3VOakE1SURjek1TNHhNRGNnTkRVeExqSTVJRGN6TXk0MU5pQTBOREpNTnpnM0xqVTRPU0F5TXpjdU16UTVXazAyTmpBdU1qWTVJREkwTlM0d01VTTJOVFV1TlRJeklESTBOQzR5TmpNZ05qVXdMalk0TWlBeU5EY3VOREl6SURZME9TNDBOVFlnTWpVeUxqQTJPRXcyTURjdU16ZzJJRFF4TVM0ME1UaEROakEyTGpFMklEUXhOaTR3TmpNZ05qQTVMakF4TXlBME1qQXVORE0wSURZeE15NDNOVGtnTkRJeExqRTRNVXcyT0RJdU5EazVJRFF6TWk0d01EWkROamczTGpJME5TQTBNekl1TnpVeklEWTVNaTR3T0RZZ05ESTVMalU1TkNBMk9UTXVNekV5SURReU5DNDVORGxNTnpNMUxqTTRNaUF5TmpVdU5UazVRemN6Tmk0Mk1EZ2dNall3TGprMU5DQTNNek11TnpVMUlESTFOaTQxT0RNZ056STVMakF4SURJMU5TNDRNelZNTmpZd0xqSTJPU0F5TkRVdU1ERmFJaUJtYVd4c1BTSjFjbXdvSTIxaGFXNHBJaUF2UGp4d1lYUm9JR1pwYkd3dGNuVnNaVDBpWlhabGJtOWtaQ0lnWTJ4cGNDMXlkV3hsUFNKbGRtVnViMlJrSWlCa1BTSk5PRFkwTGpZME15QXlPRE11T1RNM1F6ZzJOUzR4T0RZZ01qZ3pMall3TlNBNE5qVXVOekE0SURJNE5DNHlOVGNnT0RZMUxqSXpPU0F5T0RRdU5qZ3pURGcwTkM0eU5qZ2dNekF6TGpjeE9VTTRORE11T1RNNElETXdOQzR3TVRnZ09EUTBMakE1TXlBek1EUXVOVEUzSURnME5DNDFNallnTXpBMExqVTBPRXc0TlRNdU56STJJRE13TlM0eU1EZERPRFUwTGpFNE5DQXpNRFV1TWpRZ09EVTBMak15TVNBek1EVXVOemczSURnMU15NDVORElnTXpBMkxqQTNNVXc0TXpNdU9EZzBJRE15TVM0eE1USkRPRE16TGpVd05pQXpNakV1TXprMklEZ3pNeTQyTkRNZ016SXhMamswTXlBNE16UXVNVEF4SURNeU1TNDVOelpNT0RRMExqQXdOeUF6TWpJdU5qZzFRemcwTkM0ME9URWdNekl5TGpjeUlEZzBOQzQyTURVZ016SXpMak14T1NBNE5EUXVNVGMzSURNeU15NDFPRXczT1RjdU56VXlJRE0xTVM0NU5UUkROemszTGpJd09TQXpOVEl1TWpnMklEYzVOaTQyT0RjZ016VXhMall6TkNBM09UY3VNVFUySURNMU1TNHlNRGxNT0RFNExqUXdNeUF6TXpFdU9USXlRemd4T0M0M016TWdNek14TGpZeU1pQTRNVGd1TlRjM0lETXpNUzR4TWpNZ09ERTRMakUwTlNBek16RXVNRGt5VERnd09DNDNORGdnTXpNd0xqUXlRemd3T0M0eU9USWdNek13TGpNNE55QTRNRGd1TVRVMElETXlPUzQ0TkRNZ09EQTRMalV5T1NBek1qa3VOVFU0VERneU9DNHdOVFFnTXpFMExqYzBORU00TWpndU5ETWdNekUwTGpRMU9TQTRNamd1TWpreElETXhNeTQ1TVRVZ09ESTNMamd6TlNBek1UTXVPRGd5VERneE9DNHpPRGtnTXpFekxqSXdOa000TVRjdU9UQTBJRE14TXk0eE56RWdPREUzTGpjNUlETXhNaTQxTnpJZ09ERTRMakl4T0NBek1USXVNekV4VERnMk5DNDJORE1nTWpnekxqa3pOMW9pSUdacGJHdzlJbmRvYVhSbElpQXZQanhuSUhSeVlXNXpabTl5YlQwaWJXRjBjbWw0S0RBdU9UZzNPREkzSURBdU1UVTFOVFUzSUMwd0xqSTFOVEkyTVNBd0xqazJOamczTWlBeU5UQWdOek0xS1NJK1BIUmxlSFFnWm05dWRDMW1ZVzFwYkhrOUlrbHVkR1Z5TENCellXNXpMWE5sY21sbUlpQm1iMjUwTFhkbGFXZG9kRDBpWW05c1pDSWdabTl1ZEMxemFYcGxQU0kwTWlJZ1ptbHNiRDBpSTBVMVJUZEdPQ0krUm05MWJtUnllU0JVWlhOMElFRndjRHd2ZEdWNGRENDhkR1Y0ZENCbWIyNTBMV1poYldsc2VUMGlTVzUwWlhJc0lITmhibk10YzJWeWFXWWlJR1p2Ym5RdGQyVnBaMmgwUFNKdWIzSnRZV3dpSUhrOUlqUXdJaUJtYjI1MExYTnBlbVU5SWpJeUlpQm1hV3hzUFNJak4wWTRNVGt5SWo1bWIzVnVaSEo1TG1WMGFEd3ZkR1Y0ZEQ0OEwyYytQR2x0WVdkbElIZHBaSFJvUFNJeE5qY2lJR2hsYVdkb2REMGlNVFkzSWlCMGNtRnVjMlp2Y20wOUltMWhkSEpwZUNnd0xqazROemd5TnlBd0xqRTFOVFUxTnlBdE1DNHlOVFV5TmpFZ01DNDVOalk0TnpJZ05EUTBMakV4TnlBMU1qUXVNVGNwSWlCb2NtVm1QU0prWVhSaE9tbHRZV2RsTDNOMlp5dDRiV3c3WW1GelpUWTBMRkJJVGpKYWVVSnRZVmQ0YzFCVFNuVmlNalZzU1dsQ2IxcFhiRzVoU0ZFNVNXcEpNVTFFUVdsSlNHUndXa2hTYjFCVFNYbE5WR2Q2U1dsQ05HSlhlSFZqZWpCcFlVaFNNR05FYjNaTU0yUXpaSGsxTTAxNU5YWmpiV04yVFdwQmQwMURPWHBrYldOcFNVaGFjRnBZWkVOaU0yYzVTV3BCWjAxRFFYaE5hbEZuVFZSUmVFeHFWWHBOVkdzMVQxUnJOVTlVYXpWUFZHczBTV28wT0dOSFJqQmhRMEpyVUZOS1RrMVVRWFZOZW1kNlNVUkZlVTVwTkRSUFZGSk5UVU5CZDJKRVJYbE9RMEYxVFdwVk1VeFVSWGRNYW1zelQxTkJlRTFxV1hWT2FrMDFURlJWZDB4cVZURk5lVUY0VGtNME1rMTZhRFpKYVVKdFlWZDRjMUJUU1dwYVZFMHdXbXBKTWtscE9DdFFTRUpvWkVkbloxcEVNR2xVVkZsNVRHcFJNazlEUVhoTmFtdDFUV3BqTTFacVJYbE1ha0UwVGxkM01VMVROSGRPYWxGMVRWUmpkRTlUTkhoTlJGbG5UVlJCTUV4cVp6Rk5XRzlwU1VkYWNHSkhkemxKYVU1c1dtcFpNVTF0UldsTWVqUTRZMGRHTUdGRFFtdFFVMHBPVDFScmRVNUVhMmRPUkVWMVRYcFplV0pFUlhWT1JGRXlURlJGTVV4cVVUVlRSRWw1VEdwTk5FMHlkekJNYWswd1NVUlJNMHhxVVRWaFJGVXdUR3BKZUUwd2R6TlBRelEwVFZOQk5VMTVOREpOVkdSelRGUkZNMHhxVFRKTmFVRXdUR3BaTkV4VVJUTk1hbGw0VG5rd01VeHFSWGRPYVRCMVQxUk5Na3hVUlhsTWFrRTBUbFZuZVU1NU5IcE5WR3h6VFdrMGVFMXFaMmROYWxGMVRtcG5lRWxFVFhsSlJHZDFUMVJOTWtsRVRYbE1ha2t4VGxNd05FeHFhM3BPYVVFd1RHcE5NRXhVVVRSTWFrVXpVMFJSZUV4cVJYZE9NSGQ2VDFNME1FOVRRVEJOVXpSNlRtcEtOa2xwUW0xaFYzaHpVRk5KYWxwdFdtMUphVGdyVUVNNWVtUnRZeXNpSUM4K1BHUmxabk0rUEdacGJIUmxjaUJwWkQwaVpHbHphMlYwZEdVdGMyaGhaRzkzSWlCNFBTSTNNQzQzTkRnNUlpQjVQU0l4T1RVdU56RXlJaUIzYVdSMGFEMGlPVFUxTGpjek15SWdhR1ZwWjJoMFBTSTRNekl1TlRVNElpQm1hV3gwWlhKVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR052Ykc5eUxXbHVkR1Z5Y0c5c1lYUnBiMjR0Wm1sc2RHVnljejBpYzFKSFFpSStQR1psUm14dmIyUWdabXh2YjJRdGIzQmhZMmwwZVQwaU1DSWdMejQ4Wm1WQ2JHVnVaQ0JwYmowaVUyOTFjbU5sUjNKaGNHaHBZeUlnTHo0OFptVkhZWFZ6YzJsaGJrSnNkWElnYzNSa1JHVjJhV0YwYVc5dVBTSTBNaUlnTHo0OEwyWnBiSFJsY2o0OGJHbHVaV0Z5UjNKaFpHbGxiblFnYVdROUltSmhZMnRuY205MWJtUWlJSGd4UFNJMU16SXVOU0lnZVRFOUlqQWlJSGd5UFNJMU16SXVOU0lnZVRJOUlqRXdOalVpSUdkeVlXUnBaVzUwVlc1cGRITTlJblZ6WlhKVGNHRmpaVTl1VlhObElqNDhjM1J2Y0NBdlBqeHpkRzl3SUc5bVpuTmxkRDBpTVNJZ2MzUnZjQzFqYjJ4dmNqMGlJekV6TVRNeE15SWdMejQ4TDJ4cGJtVmhja2R5WVdScFpXNTBQanh5WVdScFlXeEhjbUZrYVdWdWRDQnBaRDBpWW1GamEyZHliM1Z1WkMxeVlXUnBZV3dpSUdONFBTSXdJaUJqZVQwaU1DSWdjajBpTVNJZ1ozSmhaR2xsYm5SVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR2R5WVdScFpXNTBWSEpoYm5ObWIzSnRQU0owY21GdWMyeGhkR1VvTlRNeUxqVWdOVE15TGpVcElISnZkR0YwWlNnNE9TNDVOakVwSUhOallXeGxLRGN6TlNraVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTXhNak0wTlRZaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTVRJek5EVTJJaUJ6ZEc5d0xXOXdZV05wZEhrOUlqQWlJQzgrUEM5eVlXUnBZV3hIY21Ga2FXVnVkRDQ4YkdsdVpXRnlSM0poWkdsbGJuUWdhV1E5SW1ScGMydGxkSFJsTFdkeVlXUnBaVzUwSWlCNE1UMGlPVEkxTGpZeU5pSWdlVEU5SWpJMU5pNDRPVFlpSUhneVBTSXhNell1TnpjNUlpQjVNajBpT0RBd0xqSXdNeUlnWjNKaFpHbGxiblJWYm1sMGN6MGlkWE5sY2xOd1lXTmxUMjVWYzJVaVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTXhNak0wTlRZaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTWtNek1UTkdJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEd4cGJtVmhja2R5WVdScFpXNTBJR2xrUFNKdFlXbHVJajQ4YzNSdmNDQnpkRzl3TFdOdmJHOXlQU0lqTVRJek5EVTJJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEM5a1pXWnpQand2YzNablBnPT0iLCJhY2Nlc3NfcG9pbnRfYXV0b19hcHByb3ZhbCI6ZmFsc2UsInZlcmlmaWVkIjpmYWxzZSwiYXR0cmlidXRlcyI6IFt7InRyYWl0X3R5cGUiOiAiRU5TIiwgInZhbHVlIjoiZm91bmRyeS5ldGgifSx7InRyYWl0X3R5cGUiOiAiQ29tbWl0IEhhc2giLCAidmFsdWUiOiJhZmZmM2Y2In0seyJ0cmFpdF90eXBlIjogIlJlcG9zaXRvcnkiLCAidmFsdWUiOiJodHRwczovL2dpdGh1Yi5jb20vZmxlZWt4eXovbm9uLWZ1bmdpYmxlLWFwcHMifSx7InRyYWl0X3R5cGUiOiAiVmVyc2lvbiIsICJ2YWx1ZSI6IjAifSx7InRyYWl0X3R5cGUiOiAiQ29sb3IiLCAidmFsdWUiOiIjMTIzNDU2In1dfQ==" + "data:application/json;base64,eyJuYW1lIjoiRm91bmRyeSBUZXN0IEFwcCIsImRlc2NyaXB0aW9uIjoiVGhpcyBpcyBhIHRlc3QgYXBwbGljYXRpb24gc3VibWl0dGVkIGJ5IGZvdW5kcnkgdGVzdHMuIiwib3duZXIiOiIweDkwMTkzYzk2MWE5MjYyNjFiNzU2ZDFlNWJiMjU1ZTY3ZmY5NDk4YTEiLCJleHRlcm5hbF91cmwiOiJodHRwczovL2ZvdW5kcnkudGVzdCIsImltYWdlIjoiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCM2FXUjBhRDBpTVRBMk5TSWdhR1ZwWjJoMFBTSXhNRFkxSWlCMmFXVjNRbTk0UFNJd0lEQWdNVEEyTlNBeE1EWTFJaUJtYVd4c1BTSnViMjVsSWlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhodGJHNXpPbmhzYVc1clBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHhPVGs1TDNoc2FXNXJJajQ4YzNSNWJHVWdkSGx3WlQwaWRHVjRkQzlqYzNNaVBrQnBiWEJ2Y25RZ2RYSnNLQ0pvZEhSd2N6b3ZMMlp2Ym5SekxtZHZiMmRzWldGd2FYTXVZMjl0TDJOemN6SS9abUZ0YVd4NVBVbHVkR1Z5T25kbmFIUkFOVEF3T3pZd01DSXBPend2YzNSNWJHVStQSEpsWTNRZ2QybGtkR2c5SWpFd05qVWlJR2hsYVdkb2REMGlNVEEyTlNJZ1ptbHNiRDBpZFhKc0tDTmlZV05yWjNKdmRXNWtLU0lnTHo0OGNtVmpkQ0J2Y0dGamFYUjVQU0l3TGpJaUlIZHBaSFJvUFNJeE1EWTFJaUJvWldsbmFIUTlJakV3TmpVaUlHWnBiR3c5SW5WeWJDZ2pZbUZqYTJkeWIzVnVaQzF5WVdScFlXd3BJaUF2UGp4bklHWnBiSFJsY2owaWRYSnNLQ05rYVhOclpYUjBaUzF6YUdGa2IzY3BJajQ4Y0dGMGFDQmtQU0pOT0RVM0xqSXpNU0F5TnprdU56RXlURGt3TWk0eU5DQXlPRFl1TmpjMVF6a3hNQzQxTkRjZ01qZzNMamsySURreE55NDVNVFVnTWpreUxqY3lNU0E1TWpJdU5TQXlPVGt1TnpZNFREa3pPQzQ0T1RRZ016STBMamsyTkVNNU5ESXVNalE1SURNek1DNHhNaUE1TkRNdU16RXhJRE16Tmk0ME16Y2dPVFF4TGpneU55QXpOREl1TkRBMlREa3pOeTQzT1RnZ016VTRMall4TlV3NU1qUXVNRFE1SURNMU5pNDJOVXc1TVRrdU5ERTJJRE0zTkM0d09EUk1PVE0wTGpBMk9DQXpOell1TWpSTU56a3hMamswTnlBNU1qSXVNVFV5UXpjNE9DNHhNRGtnT1RNMkxqZzVOaUEzTnpNdU5qazBJRGswTmk0ek1EZ2dOelU0TGpZMU1TQTVORE11T0RrelRERTNPUzQyTXpZZ09EVXdMamt5T0VNeE5qSXVNekU0SURnME9DNHhORGNnTVRVeExqSXhOU0E0TXpBdU9UZzNJREUxTlM0M056WWdPREUwTGpBMU1Vd3hOakF1TkRjNElEYzVOaTQxT1V3M01EUXVNekUxSURnM09TNDFOelJNT0RVM0xqSXpNU0F5TnprdU56RXlXaUlnWm1sc2JEMGlJekExTURVd05TSWdMejQ4TDJjK1BIQmhkR2dnWkQwaVRUZzBNQzR5TXpFZ01qUXdMamN4TWt3NE9EVXVNalFnTWpRM0xqWTNOVU00T1RNdU5UUTNJREkwT0M0NU5qRWdPVEF3TGpreE5TQXlOVE11TnpJeUlEa3dOUzQxSURJMk1DNDNOamhNT1RJeExqZzVOQ0F5T0RVdU9UWTFRemt5TlM0eU5Ea2dNamt4TGpFeUlEa3lOaTR6TVRFZ01qazNMalF6TnlBNU1qUXVPREkzSURNd015NDBNRFpNT1RJd0xqYzVPQ0F6TVRrdU5qRTJURGt3Tnk0d05Ea2dNekUzTGpZMVREa3dNaTQwTVRZZ016TTFMakE0TkV3NU1UY3VNRFk0SURNek55NHlOREZNTnpjMExqazBOeUE0T0RNdU1UVXlRemMzTVM0eE1Ea2dPRGszTGpnNU5pQTNOVFl1TmprMElEa3dOeTR6TURnZ056UXhMalkxTVNBNU1EUXVPRGt6VERFMk1pNDJNellnT0RFeExqa3lPRU14TkRVdU16RTRJRGd3T1M0eE5EY2dNVE0wTGpJeE5TQTNPVEV1T1RnM0lERXpPQzQzTnpZZ056YzFMakExTVV3eE5ETXVORGM0SURjMU55NDFPVXcyT0RjdU16RTFJRGcwTUM0MU56Uk1PRFF3TGpJek1TQXlOREF1TnpFeVdpSWdabWxzYkQwaWRYSnNLQ050WVdsdUtTSWdMejQ4Y0dGMGFDQm1hV3hzTFhKMWJHVTlJbVYyWlc1dlpHUWlJR05zYVhBdGNuVnNaVDBpWlhabGJtOWtaQ0lnWkQwaVRUTXhPUzQ0TkRjZ01UWXhMalV3TWtNek1UQXVNelUySURFMk1DNHdNRGNnTXpBd0xqWTNOQ0F4TmpZdU16STJJREk1T0M0eU1qRWdNVGMxTGpZeE5rd3hNemd1TnpJMElEYzNPUzQzTlRoRE1UTTJMakkzTVNBM09Ea3VNRFE0SURFME1TNDVOemNnTnprM0xqYzVJREUxTVM0ME5qZ2dOems1TGpJNE5VdzNOREF1TURZeElEZzVNUzQ1TnpORE56UTVMalUxTXlBNE9UTXVORFkzSURjMU9TNHlNelVnT0RnM0xqRTBPQ0EzTmpFdU5qZzNJRGczTnk0NE5UaE1PVEF5TGpRd05TQXpORFF1T0RVMFREZzRPUzR4TlRnZ016UXlMamMyT0V3NE9UZ3VPRGN5SURNd05TNDVOekpNT1RFeUxqRXhPU0F6TURndU1EVTVURGt4TXk0M016TWdNekF4TGprME5rTTVNVFF1T0RNM0lESTVOeTQzTmpJZ09URTBMak13T1NBeU9UTXVORGMySURreE1pNHlOVEVnTWpnNUxqa3lOMHc0T1RNdU5EZzBJREkxTnk0MU5qbERPRGt4TGpFMU15QXlOVE11TlRRNUlEZzROeTR3TmpNZ01qVXdMamd5TXlBNE9ESXVNakl4SURJMU1DNHdOakZNT0RJNExqSXdOU0F5TkRFdU5UVTBRemd5TWk0eU1qUWdNalF3TGpZeE15QTRNVFV1T0RZNUlESTBNaTQzT0RNZ09ERXhMalF5TnlBeU5EY3VNamcwVERnd05TNDJPRFlnTWpVekxqRXdNME00TURRdU1qQTFJREkxTkM0Mk1ETWdPREF5TGpBNE55QXlOVFV1TXpJMklEZ3dNQzR3T1RNZ01qVTFMakF4TTB3M09ETXVOakV4SURJMU1pNDBNVGRNTnpNMExqTWdORE01TGpFNU5rTTNNekV1TkRNNUlEUTFNQzR3TXpVZ056SXdMakUwTXlBME5UY3VOREEzSURjd09TNHdOeUEwTlRVdU5qWXpURE15T0M0NE5EY2dNemsxTGpjNE9FTXpNVGN1TnpjMElETTVOQzR3TkRVZ016RXhMakV4TnlBek9ETXVPRFExSURNeE15NDVOemdnTXpjekxqQXdOMHd6TmpZdU5USTRJREUzTXk0NU5qSk1NelkyTGpVek15QXhOek11T1RReFF6TTJOeTR5TXpRZ01UY3hMakkwSURNMk5TNDFOeklnTVRZNExqY3dNaUF6TmpJdU9ERWdNVFk0TGpJMk4wd3pNVGt1T0RRM0lERTJNUzQxTURKYVRUTTJPUzR6T1RJZ01UYzBMalF4TkV3ek5qZ3VOalV5SURFM055NHlNVGRNTXpFMkxqZzBNeUF6TnpNdU5EVTRRek14TkM0ek9TQXpPREl1TnpRNElETXlNQzR3T1RZZ016a3hMalE1SURNeU9TNDFPRGNnTXpreUxqazROVXczTURrdU9ERWdORFV5TGpnMlF6Y3hPUzR6TURFZ05EVTBMak0xTkNBM01qZ3VPVGd6SURRME9DNHdNelVnTnpNeExqUXpOaUEwTXpndU56UTFURGM0TUM0M05EY2dNalV4TGprMk5rdzNPRE11TWpRMUlESTBNaTQxTURSTU56Z3pMams0TlNBeU16a3VOekF4VERNMk9TNHpPVElnTVRjMExqUXhORm9pSUdacGJHdzlJaU14TXpFek1UWWlJQzgrUEhCaGRHZ2dabWxzYkMxeWRXeGxQU0psZG1WdWIyUmtJaUJqYkdsd0xYSjFiR1U5SW1WMlpXNXZaR1FpSUhOMGNtOXJaVDBpZFhKc0tDTnRZV2x1S1NJZ2MzUnliMnRsTFhkcFpIUm9QU0kwSWlCemRISnZhMlV0YkdsdVpXTmhjRDBpY205MWJtUWlJSE4wY205clpTMXNhVzVsYW05cGJqMGljbTkxYm1RaUlHUTlJazB6TVRrdU9EUTNJREUyTVM0MU1ESkRNekV3TGpNMU5pQXhOakF1TURBM0lETXdNQzQyTnpRZ01UWTJMak15TmlBeU9UZ3VNakl4SURFM05TNDJNVFpNTVRNNExqY3lOQ0EzTnprdU56VTRRekV6Tmk0eU56RWdOemc1TGpBME9DQXhOREV1T1RjM0lEYzVOeTQzT1NBeE5URXVORFk0SURjNU9TNHlPRFZNTnpRd0xqQTJNU0E0T1RFdU9UY3pRemMwT1M0MU5UTWdPRGt6TGpRMk55QTNOVGt1TWpNMUlEZzROeTR4TkRnZ056WXhMalk0TnlBNE56Y3VPRFU0VERrd01pNDBNRFVnTXpRMExqZzFORXc0T0RrdU1UVTRJRE0wTWk0M05qaE1PRGs0TGpnM01pQXpNRFV1T1RjeVREa3hNaTR4TVRrZ016QTRMakExT1V3NU1UTXVOek16SURNd01TNDVORFpET1RFMExqZ3pOeUF5T1RjdU56WXlJRGt4TkM0ek1Ea2dNamt6TGpRM05pQTVNVEl1TWpVeElESTRPUzQ1TWpkTU9Ea3pMalE0TkNBeU5UY3VOVFk1UXpnNU1TNHhOVE1nTWpVekxqVTBPU0E0T0RjdU1EWXpJREkxTUM0NE1qTWdPRGd5TGpJeU1TQXlOVEF1TURZeFREZ3lPQzR5TURVZ01qUXhMalUxTkVNNE1qSXVNakkwSURJME1DNDJNVE1nT0RFMUxqZzJPU0F5TkRJdU56Z3pJRGd4TVM0ME1qY2dNalEzTGpJNE5FdzRNRFV1TmpnMklESTFNeTR4TURORE9EQTBMakl3TlNBeU5UUXVOakF6SURnd01pNHdPRGNnTWpVMUxqTXlOaUE0TURBdU1Ea3pJREkxTlM0d01UTk1Oemd6TGpZeE1TQXlOVEl1TkRFM1REY3pOQzR6SURRek9TNHhPVFpETnpNeExqUXpPU0EwTlRBdU1ETTFJRGN5TUM0eE5ETWdORFUzTGpRd055QTNNRGt1TURjZ05EVTFMalkyTTB3ek1qZ3VPRFEzSURNNU5TNDNPRGhETXpFM0xqYzNOQ0F6T1RRdU1EUTFJRE14TVM0eE1UY2dNemd6TGpnME5TQXpNVE11T1RjNElETTNNeTR3TURkTU16WTJMalV5T0NBeE56TXVPVFl5VERNMk5pNDFNek1nTVRjekxqazBNVU16TmpjdU1qTTBJREUzTVM0eU5DQXpOalV1TlRjeUlERTJPQzQzTURJZ016WXlMamd4SURFMk9DNHlOamRNTXpFNUxqZzBOeUF4TmpFdU5UQXlXazB6TmprdU16a3lJREUzTkM0ME1UUk1Nelk0TGpZMU1pQXhOemN1TWpFM1RETXhOaTQ0TkRNZ016Y3pMalExT0VNek1UUXVNemtnTXpneUxqYzBPQ0F6TWpBdU1EazJJRE01TVM0ME9TQXpNamt1TlRnM0lETTVNaTQ1T0RWTU56QTVMamd4SURRMU1pNDROa00zTVRrdU16QXhJRFExTkM0ek5UUWdOekk0TGprNE15QTBORGd1TURNMUlEY3pNUzQwTXpZZ05ETTRMamMwTlV3M09EQXVOelEzSURJMU1TNDVOalpNTnpnekxqSTBOU0F5TkRJdU5UQTBURGM0TXk0NU9EVWdNak01TGpjd01Vd3pOamt1TXpreUlERTNOQzQwTVRSYUlpQm1hV3hzUFNKMWNtd29JMlJwYzJ0bGRIUmxMV2R5WVdScFpXNTBLU0lnWm1sc2JDMXZjR0ZqYVhSNVBTSXdMaklpSUM4K1BIQmhkR2dnWkQwaVRUTXpOUzR6T0NBeU1EZ3VNVEV6UXpNek5TNDVNaklnTWpBNExqRTVPQ0F6TXpZdU5ERTNJREl3Tnk0Mk9EWWdNek0yTGpJNE15QXlNRGN1TVRjNVRETXpNQzR6T1NBeE9EUXVOemsxUXpNek1DNHlORGtnTVRnMExqSTJNU0F6TWprdU5USTVJREU0TkM0eE5EZ2dNekk1TGpFeU9TQXhPRFF1TlRrM1RETXhNaTR6TlRnZ01qQXpMalF4TVVNek1URXVPVGM0SURJd015NDRNemdnTXpFeUxqRTNOQ0F5TURRdU5EVTRJRE14TWk0M01UWWdNakEwTGpVME5Fd3pNVGN1T1RZeUlESXdOUzR6TjBNek1UZ3VNelUzSURJd05TNDBNeklnTXpFNExqVTVOU0F5TURVdU56azJJRE14T0M0ME9UTWdNakEyTGpFNE0wd3pNVFF1TnlBeU1qQXVOVFV4UXpNeE5DNDFPVGNnTWpJd0xqa3pPQ0F6TVRRdU9ETTFJREl5TVM0ek1ESWdNekUxTGpJek1TQXlNakV1TXpZMFRETXlOQzQxTXprZ01qSXlMamd6UXpNeU5DNDVNelVnTWpJeUxqZzVNeUF6TWpVdU16TTRJREl5TWk0Mk1qa2dNekkxTGpRMElESXlNaTR5TkRKTU16STVMakl6TXlBeU1EY3VPRGMxUXpNeU9TNHpNellnTWpBM0xqUTRPQ0F6TWprdU56TTVJREl3Tnk0eU1qUWdNek13TGpFek5TQXlNRGN1TWpnMlRETXpOUzR6T0NBeU1EZ3VNVEV6V2lJZ1ptbHNiRDBpZFhKc0tDTnRZV2x1S1NJZ0x6NDhjR0YwYUNCa1BTSk5NekU1TGpJNE1pQXlOamt1TURnM1F6TXhPUzQ0TWpRZ01qWTVMakUzTXlBek1qQXVNekU1SURJMk9DNDJOakVnTXpJd0xqRTROaUF5TmpndU1UVTBURE14TkM0eU9USWdNalExTGpjM1F6TXhOQzR4TlRFZ01qUTFMakl6TmlBek1UTXVORE14SURJME5TNHhNak1nTXpFekxqQXpNU0F5TkRVdU5UY3lUREk1Tmk0eU5qRWdNalkwTGpNNE5rTXlPVFV1T0RnZ01qWTBMamd4TWlBeU9UWXVNRGMySURJMk5TNDBNek1nTWprMkxqWXhPQ0F5TmpVdU5URTRURE13TVM0NE5qUWdNalkyTGpNME5FTXpNREl1TWpVNUlESTJOaTQwTURjZ016QXlMalE1TnlBeU5qWXVOemN4SURNd01pNHpPVFVnTWpZM0xqRTFPRXd5T1RndU5qQXlJREk0TVM0MU1qWkRNams0TGpVZ01qZ3hMamt4TXlBeU9UZ3VOek0zSURJNE1pNHlOemNnTWprNUxqRXpNeUF5T0RJdU16TTVURE13T0M0ME5ERWdNamd6TGpnd05VTXpNRGd1T0RNM0lESTRNeTQ0TmpjZ016QTVMakkwSURJNE15NDJNRFFnTXpBNUxqTTBNeUF5T0RNdU1qRTNURE14TXk0eE16WWdNalk0TGpnME9VTXpNVE11TWpNNElESTJPQzQwTmpJZ016RXpMalkwTVNBeU5qZ3VNVGs1SURNeE5DNHdNemNnTWpZNExqSTJNVXd6TVRrdU1qZ3lJREkyT1M0d09EZGFJaUJtYVd4c1BTSmliR0ZqYXlJZ1ptbHNiQzF2Y0dGamFYUjVQU0l3TGpVaUlDOCtQSEJoZEdnZ1pEMGlUVE13TXk0eE9EUWdNek13TGpBMk1rTXpNRE11TnpJMklETXpNQzR4TkRnZ016QTBMakl5TVNBek1qa3VOak0ySURNd05DNHdPRGdnTXpJNUxqRXlPRXd5T1RndU1UazBJRE13Tmk0M05EVkRNams0TGpBMU15QXpNRFl1TWpFeElESTVOeTR6TXpNZ016QTJMakE1T0NBeU9UWXVPVE16SURNd05pNDFORGRNTWpnd0xqRTJNeUF6TWpVdU16WXhRekkzT1M0M09ESWdNekkxTGpjNE55QXlOemt1T1RjNUlETXlOaTQwTURnZ01qZ3dMalV5SURNeU5pNDBPVE5NTWpnMUxqYzJOaUF6TWpjdU16RTVRekk0Tmk0eE5qRWdNekkzTGpNNE1pQXlPRFl1TXprNUlETXlOeTQzTkRZZ01qZzJMakk1TnlBek1qZ3VNVE16VERJNE1pNDFNRFFnTXpReUxqVXdNVU15T0RJdU5EQXlJRE0wTWk0NE9EZ2dNamd5TGpZek9TQXpORE11TWpVeUlESTRNeTR3TXpVZ016UXpMak14TkV3eU9USXVNelEwSURNME5DNDNPRU15T1RJdU56TTVJRE0wTkM0NE5ESWdNamt6TGpFME1pQXpORFF1TlRjNUlESTVNeTR5TkRVZ016UTBMakU1TWt3eU9UY3VNRE00SURNeU9TNDRNalJETWprM0xqRTBJRE15T1M0ME16Y2dNamszTGpVME15QXpNamt1TVRjMElESTVOeTQ1TXprZ016STVMakl6Tmt3ek1ETXVNVGcwSURNek1DNHdOakphSWlCbWFXeHNQU0ppYkdGamF5SWdabWxzYkMxdmNHRmphWFI1UFNJd0xqVWlJQzgrUEhCaGRHZ2djM1J5YjJ0bFBTSjFjbXdvSTIxaGFXNHBJaUJ6ZEhKdmEyVXRkMmxrZEdnOUlqWWlJSE4wY205clpTMXNhVzVsWTJGd1BTSnliM1Z1WkNJZ2MzUnliMnRsTFd4cGJtVnFiMmx1UFNKeWIzVnVaQ0lnWkQwaVRUSTVNQzR4TURrZ05EWXpMalF4T0VNeU9USXVNelU0SURRMU5DNDVNRElnTXpBeExqSXpNeUEwTkRrdU1URWdNekE1TGprek15QTBOVEF1TkRoTU56Y3hMakEzSURVeU15NHdPVFpETnpjNUxqYzNJRFV5TkM0ME5qY2dOemcxSURVek1pNDBPQ0EzT0RJdU56VXlJRFUwTUM0NU9UWk1Oamt5TGpBNE5pQTRPRFF1TkRFNFRERTVPUzQwTkRNZ09EQTJMamcwVERJNU1DNHhNRGtnTkRZekxqUXhPRm9pSUdacGJHdzlJbUpzWVdOcklpQm1hV3hzTFc5d1lXTnBkSGs5SWpBdU1UUWlJQzgrUEhCaGRHZ2dabWxzYkMxeWRXeGxQU0psZG1WdWIyUmtJaUJqYkdsd0xYSjFiR1U5SW1WMlpXNXZaR1FpSUhOMGNtOXJaVDBpZFhKc0tDTnRZV2x1S1NJZ2MzUnliMnRsTFhkcFpIUm9QU0kySWlCemRISnZhMlV0YkdsdVpXTmhjRDBpY205MWJtUWlJSE4wY205clpTMXNhVzVsYW05cGJqMGljbTkxYm1RaUlHUTlJazAzT0RjdU5UZzVJREl6Tnk0ek5EbE1ORFl3TGpNMU5DQXhPRFV1T0RFNFREUXdOaTR6TWpVZ016a3dMalEyT1VNME1ETXVPRGN5SURNNU9TNDNOVGtnTkRBNUxqVTNPQ0EwTURndU5UQXhJRFF4T1M0d05qa2dOREE1TGprNU5rdzNNVEV1T1RNMElEUTFOaTR4TVRSRE56SXhMalF5TlNBME5UY3VOakE1SURjek1TNHhNRGNnTkRVeExqSTVJRGN6TXk0MU5pQTBOREpNTnpnM0xqVTRPU0F5TXpjdU16UTVXazAyTmpBdU1qWTVJREkwTlM0d01VTTJOVFV1TlRJeklESTBOQzR5TmpNZ05qVXdMalk0TWlBeU5EY3VOREl6SURZME9TNDBOVFlnTWpVeUxqQTJPRXcyTURjdU16ZzJJRFF4TVM0ME1UaEROakEyTGpFMklEUXhOaTR3TmpNZ05qQTVMakF4TXlBME1qQXVORE0wSURZeE15NDNOVGtnTkRJeExqRTRNVXcyT0RJdU5EazVJRFF6TWk0d01EWkROamczTGpJME5TQTBNekl1TnpVeklEWTVNaTR3T0RZZ05ESTVMalU1TkNBMk9UTXVNekV5SURReU5DNDVORGxNTnpNMUxqTTRNaUF5TmpVdU5UazVRemN6Tmk0Mk1EZ2dNall3TGprMU5DQTNNek11TnpVMUlESTFOaTQxT0RNZ056STVMakF4SURJMU5TNDRNelZNTmpZd0xqSTJPU0F5TkRVdU1ERmFJaUJtYVd4c1BTSjFjbXdvSTIxaGFXNHBJaUF2UGp4d1lYUm9JR1pwYkd3dGNuVnNaVDBpWlhabGJtOWtaQ0lnWTJ4cGNDMXlkV3hsUFNKbGRtVnViMlJrSWlCa1BTSk5PRFkwTGpZME15QXlPRE11T1RNM1F6ZzJOUzR4T0RZZ01qZ3pMall3TlNBNE5qVXVOekE0SURJNE5DNHlOVGNnT0RZMUxqSXpPU0F5T0RRdU5qZ3pURGcwTkM0eU5qZ2dNekF6TGpjeE9VTTRORE11T1RNNElETXdOQzR3TVRnZ09EUTBMakE1TXlBek1EUXVOVEUzSURnME5DNDFNallnTXpBMExqVTBPRXc0TlRNdU56STJJRE13TlM0eU1EZERPRFUwTGpFNE5DQXpNRFV1TWpRZ09EVTBMak15TVNBek1EVXVOemczSURnMU15NDVORElnTXpBMkxqQTNNVXc0TXpNdU9EZzBJRE15TVM0eE1USkRPRE16TGpVd05pQXpNakV1TXprMklEZ3pNeTQyTkRNZ016SXhMamswTXlBNE16UXVNVEF4SURNeU1TNDVOelpNT0RRMExqQXdOeUF6TWpJdU5qZzFRemcwTkM0ME9URWdNekl5TGpjeUlEZzBOQzQyTURVZ016SXpMak14T1NBNE5EUXVNVGMzSURNeU15NDFPRXczT1RjdU56VXlJRE0xTVM0NU5UUkROemszTGpJd09TQXpOVEl1TWpnMklEYzVOaTQyT0RjZ016VXhMall6TkNBM09UY3VNVFUySURNMU1TNHlNRGxNT0RFNExqUXdNeUF6TXpFdU9USXlRemd4T0M0M016TWdNek14TGpZeU1pQTRNVGd1TlRjM0lETXpNUzR4TWpNZ09ERTRMakUwTlNBek16RXVNRGt5VERnd09DNDNORGdnTXpNd0xqUXlRemd3T0M0eU9USWdNek13TGpNNE55QTRNRGd1TVRVMElETXlPUzQ0TkRNZ09EQTRMalV5T1NBek1qa3VOVFU0VERneU9DNHdOVFFnTXpFMExqYzBORU00TWpndU5ETWdNekUwTGpRMU9TQTRNamd1TWpreElETXhNeTQ1TVRVZ09ESTNMamd6TlNBek1UTXVPRGd5VERneE9DNHpPRGtnTXpFekxqSXdOa000TVRjdU9UQTBJRE14TXk0eE56RWdPREUzTGpjNUlETXhNaTQxTnpJZ09ERTRMakl4T0NBek1USXVNekV4VERnMk5DNDJORE1nTWpnekxqa3pOMW9pSUdacGJHdzlJbmRvYVhSbElpQXZQanhuSUhSeVlXNXpabTl5YlQwaWJXRjBjbWw0S0RBdU9UZzNPREkzSURBdU1UVTFOVFUzSUMwd0xqSTFOVEkyTVNBd0xqazJOamczTWlBeU5UQWdOek0xS1NJK1BIUmxlSFFnWm05dWRDMW1ZVzFwYkhrOUlrbHVkR1Z5TENCellXNXpMWE5sY21sbUlpQm1iMjUwTFhkbGFXZG9kRDBpWW05c1pDSWdabTl1ZEMxemFYcGxQU0kwTWlJZ1ptbHNiRDBpSTBVMVJUZEdPQ0krUm05MWJtUnllU0JVWlhOMElFRndjRHd2ZEdWNGRENDhkR1Y0ZENCbWIyNTBMV1poYldsc2VUMGlTVzUwWlhJc0lITmhibk10YzJWeWFXWWlJR1p2Ym5RdGQyVnBaMmgwUFNKdWIzSnRZV3dpSUhrOUlqUXdJaUJtYjI1MExYTnBlbVU5SWpJeUlpQm1hV3hzUFNJak4wWTRNVGt5SWo1bWIzVnVaSEo1TG1WMGFEd3ZkR1Y0ZEQ0OEwyYytQR2x0WVdkbElIZHBaSFJvUFNJeE5qY2lJR2hsYVdkb2REMGlNVFkzSWlCMGNtRnVjMlp2Y20wOUltMWhkSEpwZUNnd0xqazROemd5TnlBd0xqRTFOVFUxTnlBdE1DNHlOVFV5TmpFZ01DNDVOalk0TnpJZ05EUTBMakV4TnlBMU1qUXVNVGNwSWlCb2NtVm1QU0prWVhSaE9tbHRZV2RsTDNOMlp5dDRiV3c3WW1GelpUWTBMRkJJVGpKYWVVSnRZVmQ0YzFCVFNuVmlNalZzU1dsQ2IxcFhiRzVoU0ZFNVNXcEpNVTFFUVdsSlNHUndXa2hTYjFCVFNYbE5WR2Q2U1dsQ05HSlhlSFZqZWpCcFlVaFNNR05FYjNaTU0yUXpaSGsxTTAxNU5YWmpiV04yVFdwQmQwMURPWHBrYldOcFNVaGFjRnBZWkVOaU0yYzVTV3BCWjAxRFFYaE5hbEZuVFZSUmVFeHFWWHBOVkdzMVQxUnJOVTlVYXpWUFZHczBTV28wT0dOSFJqQmhRMEpyVUZOS1RrMVVRWFZOZW1kNlNVUkZlVTVwTkRSUFZGSk5UVU5CZDJKRVJYbE9RMEYxVFdwVk1VeFVSWGRNYW1zelQxTkJlRTFxV1hWT2FrMDFURlJWZDB4cVZURk5lVUY0VGtNME1rMTZhRFpKYVVKdFlWZDRjMUJUU1dwYVZFMHdXbXBKTWtscE9DdFFTRUpvWkVkbloxcEVNR2xVVkZsNVRHcFJNazlEUVhoTmFtdDFUV3BqTTFacVJYbE1ha0UwVGxkM01VMVROSGRPYWxGMVRWUmpkRTlUTkhoTlJGbG5UVlJCTUV4cVp6Rk5XRzlwU1VkYWNHSkhkemxKYVU1c1dtcFpNVTF0UldsTWVqUTRZMGRHTUdGRFFtdFFVMHBPVDFScmRVNUVhMmRPUkVWMVRYcFplV0pFUlhWT1JGRXlURlJGTVV4cVVUVlRSRWw1VEdwTk5FMHlkekJNYWswd1NVUlJNMHhxVVRWaFJGVXdUR3BKZUUwd2R6TlBRelEwVFZOQk5VMTVOREpOVkdSelRGUkZNMHhxVFRKTmFVRXdUR3BaTkV4VVJUTk1hbGw0VG5rd01VeHFSWGRPYVRCMVQxUk5Na3hVUlhsTWFrRTBUbFZuZVU1NU5IcE5WR3h6VFdrMGVFMXFaMmROYWxGMVRtcG5lRWxFVFhsSlJHZDFUMVJOTWtsRVRYbE1ha2t4VGxNd05FeHFhM3BPYVVFd1RHcE5NRXhVVVRSTWFrVXpVMFJSZUV4cVJYZE9NSGQ2VDFNME1FOVRRVEJOVXpSNlRtcEtOa2xwUW0xaFYzaHpVRk5KYWxwdFdtMUphVGdyVUVNNWVtUnRZeXNpSUM4K1BHUmxabk0rUEdacGJIUmxjaUJwWkQwaVpHbHphMlYwZEdVdGMyaGhaRzkzSWlCNFBTSTNNQzQzTkRnNUlpQjVQU0l4T1RVdU56RXlJaUIzYVdSMGFEMGlPVFUxTGpjek15SWdhR1ZwWjJoMFBTSTRNekl1TlRVNElpQm1hV3gwWlhKVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR052Ykc5eUxXbHVkR1Z5Y0c5c1lYUnBiMjR0Wm1sc2RHVnljejBpYzFKSFFpSStQR1psUm14dmIyUWdabXh2YjJRdGIzQmhZMmwwZVQwaU1DSWdMejQ4Wm1WQ2JHVnVaQ0JwYmowaVUyOTFjbU5sUjNKaGNHaHBZeUlnTHo0OFptVkhZWFZ6YzJsaGJrSnNkWElnYzNSa1JHVjJhV0YwYVc5dVBTSTBNaUlnTHo0OEwyWnBiSFJsY2o0OGJHbHVaV0Z5UjNKaFpHbGxiblFnYVdROUltSmhZMnRuY205MWJtUWlJSGd4UFNJMU16SXVOU0lnZVRFOUlqQWlJSGd5UFNJMU16SXVOU0lnZVRJOUlqRXdOalVpSUdkeVlXUnBaVzUwVlc1cGRITTlJblZ6WlhKVGNHRmpaVTl1VlhObElqNDhjM1J2Y0NBdlBqeHpkRzl3SUc5bVpuTmxkRDBpTVNJZ2MzUnZjQzFqYjJ4dmNqMGlJekV6TVRNeE15SWdMejQ4TDJ4cGJtVmhja2R5WVdScFpXNTBQanh5WVdScFlXeEhjbUZrYVdWdWRDQnBaRDBpWW1GamEyZHliM1Z1WkMxeVlXUnBZV3dpSUdONFBTSXdJaUJqZVQwaU1DSWdjajBpTVNJZ1ozSmhaR2xsYm5SVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR2R5WVdScFpXNTBWSEpoYm5ObWIzSnRQU0owY21GdWMyeGhkR1VvTlRNeUxqVWdOVE15TGpVcElISnZkR0YwWlNnNE9TNDVOakVwSUhOallXeGxLRGN6TlNraVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTXhNak0wTlRZaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTVRJek5EVTJJaUJ6ZEc5d0xXOXdZV05wZEhrOUlqQWlJQzgrUEM5eVlXUnBZV3hIY21Ga2FXVnVkRDQ4YkdsdVpXRnlSM0poWkdsbGJuUWdhV1E5SW1ScGMydGxkSFJsTFdkeVlXUnBaVzUwSWlCNE1UMGlPVEkxTGpZeU5pSWdlVEU5SWpJMU5pNDRPVFlpSUhneVBTSXhNell1TnpjNUlpQjVNajBpT0RBd0xqSXdNeUlnWjNKaFpHbGxiblJWYm1sMGN6MGlkWE5sY2xOd1lXTmxUMjVWYzJVaVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTXhNak0wTlRZaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTWtNek1UTkdJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEd4cGJtVmhja2R5WVdScFpXNTBJR2xrUFNKdFlXbHVJajQ4YzNSdmNDQnpkRzl3TFdOdmJHOXlQU0lqTVRJek5EVTJJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEM5a1pXWnpQand2YzNablBnPT0iLCJhY2Nlc3NfcG9pbnRfYXV0b19hcHByb3ZhbCI6ZmFsc2UsInZlcmlmaWVkIjpmYWxzZSwiYXR0cmlidXRlcyI6IFt7InRyYWl0X3R5cGUiOiAiRU5TIiwgInZhbHVlIjoiZm91bmRyeS5ldGgifSx7InRyYWl0X3R5cGUiOiAiQ29tbWl0IEhhc2giLCAidmFsdWUiOiJhZmZmM2Y2In0seyJ0cmFpdF90eXBlIjogIlJlcG9zaXRvcnkiLCAidmFsdWUiOiJodHRwczovL2dpdGh1Yi5jb20vZmxlZWt4eXovbm9uLWZ1bmdpYmxlLWFwcHMifSx7InRyYWl0X3R5cGUiOiAiVmVyc2lvbiIsICJ2YWx1ZSI6IjAifSx7InRyYWl0X3R5cGUiOiAiQ29sb3IiLCAidmFsdWUiOiIjMTIzNDU2In1dfQ==" ); } @@ -55,6 +55,7 @@ contract Test_FleekERC721_TokenURI is Test_FleekERC721_Base, Test_FleekERC721_To CuT.setTokenName(tokenId, "New App Name"); CuT.setTokenDescription(tokenId, "New description for the app."); CuT.setTokenExternalURL(tokenId, "https://new-url.com"); + transferENS("new-ens.eth", deployer); CuT.setTokenENS(tokenId, "new-ens.eth"); CuT.setTokenBuild(tokenId, "ce1a3fc141e29f8e1d00a654e156c4982d7711bf", "https://github.com/other/repo"); CuT.setTokenLogoAndColor(tokenId, TestConstants.LOGO_1, 0x654321); @@ -63,7 +64,7 @@ contract Test_FleekERC721_TokenURI is Test_FleekERC721_Base, Test_FleekERC721_To string memory uri = CuT.tokenURI(tokenId); assertEq( uri, - "data:application/json;base64,eyJuYW1lIjoiTmV3IEFwcCBOYW1lIiwiZGVzY3JpcHRpb24iOiJOZXcgZGVzY3JpcHRpb24gZm9yIHRoZSBhcHAuIiwib3duZXIiOiIweDM0YTFkM2ZmZjM5NTg4NDNjNDNhZDgwZjMwYjk0YzUxMDY0NWMzMTYiLCJleHRlcm5hbF91cmwiOiJodHRwczovL25ldy11cmwuY29tIiwiaW1hZ2UiOiJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUIzYVdSMGFEMGlNVEEyTlNJZ2FHVnBaMmgwUFNJeE1EWTFJaUIyYVdWM1FtOTRQU0l3SURBZ01UQTJOU0F4TURZMUlpQm1hV3hzUFNKdWIyNWxJaUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSGh0Ykc1ek9uaHNhVzVyUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMM2hzYVc1cklqNDhjM1I1YkdVZ2RIbHdaVDBpZEdWNGRDOWpjM01pUGtCcGJYQnZjblFnZFhKc0tDSm9kSFJ3Y3pvdkwyWnZiblJ6TG1kdmIyZHNaV0Z3YVhNdVkyOXRMMk56Y3pJL1ptRnRhV3g1UFVsdWRHVnlPbmRuYUhSQU5UQXdPell3TUNJcE96d3ZjM1I1YkdVK1BISmxZM1FnZDJsa2RHZzlJakV3TmpVaUlHaGxhV2RvZEQwaU1UQTJOU0lnWm1sc2JEMGlkWEpzS0NOaVlXTnJaM0p2ZFc1a0tTSWdMejQ4Y21WamRDQnZjR0ZqYVhSNVBTSXdMaklpSUhkcFpIUm9QU0l4TURZMUlpQm9aV2xuYUhROUlqRXdOalVpSUdacGJHdzlJblZ5YkNnalltRmphMmR5YjNWdVpDMXlZV1JwWVd3cElpQXZQanhuSUdacGJIUmxjajBpZFhKc0tDTmthWE5yWlhSMFpTMXphR0ZrYjNjcElqNDhjR0YwYUNCa1BTSk5PRFUzTGpJek1TQXlOemt1TnpFeVREa3dNaTR5TkNBeU9EWXVOamMxUXpreE1DNDFORGNnTWpnM0xqazJJRGt4Tnk0NU1UVWdNamt5TGpjeU1TQTVNakl1TlNBeU9Ua3VOelk0VERrek9DNDRPVFFnTXpJMExqazJORU01TkRJdU1qUTVJRE16TUM0eE1pQTVORE11TXpFeElETXpOaTQwTXpjZ09UUXhMamd5TnlBek5ESXVOREEyVERrek55NDNPVGdnTXpVNExqWXhOVXc1TWpRdU1EUTVJRE0xTmk0Mk5VdzVNVGt1TkRFMklETTNOQzR3T0RSTU9UTTBMakEyT0NBek56WXVNalJNTnpreExqazBOeUE1TWpJdU1UVXlRemM0T0M0eE1Ea2dPVE0yTGpnNU5pQTNOek11TmprMElEazBOaTR6TURnZ056VTRMalkxTVNBNU5ETXVPRGt6VERFM09TNDJNellnT0RVd0xqa3lPRU14TmpJdU16RTRJRGcwT0M0eE5EY2dNVFV4TGpJeE5TQTRNekF1T1RnM0lERTFOUzQzTnpZZ09ERTBMakExTVV3eE5qQXVORGM0SURjNU5pNDFPVXczTURRdU16RTFJRGczT1M0MU56Uk1PRFUzTGpJek1TQXlOemt1TnpFeVdpSWdabWxzYkQwaUl6QTFNRFV3TlNJZ0x6NDhMMmMrUEhCaGRHZ2daRDBpVFRnME1DNHlNekVnTWpRd0xqY3hNa3c0T0RVdU1qUWdNalEzTGpZM05VTTRPVE11TlRRM0lESTBPQzQ1TmpFZ09UQXdMamt4TlNBeU5UTXVOekl5SURrd05TNDFJREkyTUM0M05qaE1PVEl4TGpnNU5DQXlPRFV1T1RZMVF6a3lOUzR5TkRrZ01qa3hMakV5SURreU5pNHpNVEVnTWprM0xqUXpOeUE1TWpRdU9ESTNJRE13TXk0ME1EWk1PVEl3TGpjNU9DQXpNVGt1TmpFMlREa3dOeTR3TkRrZ016RTNMalkxVERrd01pNDBNVFlnTXpNMUxqQTRORXc1TVRjdU1EWTRJRE16Tnk0eU5ERk1OemMwTGprME55QTRPRE11TVRVeVF6YzNNUzR4TURrZ09EazNMamc1TmlBM05UWXVOamswSURrd055NHpNRGdnTnpReExqWTFNU0E1TURRdU9Ea3pUREUyTWk0Mk16WWdPREV4TGpreU9FTXhORFV1TXpFNElEZ3dPUzR4TkRjZ01UTTBMakl4TlNBM09URXVPVGczSURFek9DNDNOellnTnpjMUxqQTFNVXd4TkRNdU5EYzRJRGMxTnk0MU9VdzJPRGN1TXpFMUlEZzBNQzQxTnpSTU9EUXdMakl6TVNBeU5EQXVOekV5V2lJZ1ptbHNiRDBpZFhKc0tDTnRZV2x1S1NJZ0x6NDhjR0YwYUNCbWFXeHNMWEoxYkdVOUltVjJaVzV2WkdRaUlHTnNhWEF0Y25Wc1pUMGlaWFpsYm05a1pDSWdaRDBpVFRNeE9TNDRORGNnTVRZeExqVXdNa016TVRBdU16VTJJREUyTUM0d01EY2dNekF3TGpZM05DQXhOall1TXpJMklESTVPQzR5TWpFZ01UYzFMall4Tmt3eE16Z3VOekkwSURjM09TNDNOVGhETVRNMkxqSTNNU0EzT0RrdU1EUTRJREUwTVM0NU56Y2dOemszTGpjNUlERTFNUzQwTmpnZ056azVMakk0TlV3M05EQXVNRFl4SURnNU1TNDVOek5ETnpRNUxqVTFNeUE0T1RNdU5EWTNJRGMxT1M0eU16VWdPRGczTGpFME9DQTNOakV1TmpnM0lEZzNOeTQ0TlRoTU9UQXlMalF3TlNBek5EUXVPRFUwVERnNE9TNHhOVGdnTXpReUxqYzJPRXc0T1RndU9EY3lJRE13TlM0NU56Sk1PVEV5TGpFeE9TQXpNRGd1TURVNVREa3hNeTQzTXpNZ016QXhMamswTmtNNU1UUXVPRE0zSURJNU55NDNOaklnT1RFMExqTXdPU0F5T1RNdU5EYzJJRGt4TWk0eU5URWdNamc1TGpreU4wdzRPVE11TkRnMElESTFOeTQxTmpsRE9Ea3hMakUxTXlBeU5UTXVOVFE1SURnNE55NHdOak1nTWpVd0xqZ3lNeUE0T0RJdU1qSXhJREkxTUM0d05qRk1PREk0TGpJd05TQXlOREV1TlRVMFF6Z3lNaTR5TWpRZ01qUXdMall4TXlBNE1UVXVPRFk1SURJME1pNDNPRE1nT0RFeExqUXlOeUF5TkRjdU1qZzBURGd3TlM0Mk9EWWdNalV6TGpFd00wTTRNRFF1TWpBMUlESTFOQzQyTURNZ09EQXlMakE0TnlBeU5UVXVNekkySURnd01DNHdPVE1nTWpVMUxqQXhNMHczT0RNdU5qRXhJREkxTWk0ME1UZE1Oek0wTGpNZ05ETTVMakU1TmtNM016RXVORE01SURRMU1DNHdNelVnTnpJd0xqRTBNeUEwTlRjdU5EQTNJRGN3T1M0d055QTBOVFV1TmpZelRETXlPQzQ0TkRjZ016azFMamM0T0VNek1UY3VOemMwSURNNU5DNHdORFVnTXpFeExqRXhOeUF6T0RNdU9EUTFJRE14TXk0NU56Z2dNemN6TGpBd04wd3pOall1TlRJNElERTNNeTQ1TmpKTU16WTJMalV6TXlBeE56TXVPVFF4UXpNMk55NHlNelFnTVRjeExqSTBJRE0yTlM0MU56SWdNVFk0TGpjd01pQXpOakl1T0RFZ01UWTRMakkyTjB3ek1Ua3VPRFEzSURFMk1TNDFNREphVFRNMk9TNHpPVElnTVRjMExqUXhORXd6TmpndU5qVXlJREUzTnk0eU1UZE1NekUyTGpnME15QXpOek11TkRVNFF6TXhOQzR6T1NBek9ESXVOelE0SURNeU1DNHdPVFlnTXpreExqUTVJRE15T1M0MU9EY2dNemt5TGprNE5VdzNNRGt1T0RFZ05EVXlMamcyUXpjeE9TNHpNREVnTkRVMExqTTFOQ0EzTWpndU9UZ3pJRFEwT0M0d016VWdOek14TGpRek5pQTBNemd1TnpRMVREYzRNQzQzTkRjZ01qVXhMamsyTmt3M09ETXVNalExSURJME1pNDFNRFJNTnpnekxqazROU0F5TXprdU56QXhURE0yT1M0ek9USWdNVGMwTGpReE5Gb2lJR1pwYkd3OUlpTXhNekV6TVRZaUlDOCtQSEJoZEdnZ1ptbHNiQzF5ZFd4bFBTSmxkbVZ1YjJSa0lpQmpiR2x3TFhKMWJHVTlJbVYyWlc1dlpHUWlJSE4wY205clpUMGlkWEpzS0NOdFlXbHVLU0lnYzNSeWIydGxMWGRwWkhSb1BTSTBJaUJ6ZEhKdmEyVXRiR2x1WldOaGNEMGljbTkxYm1RaUlITjBjbTlyWlMxc2FXNWxhbTlwYmowaWNtOTFibVFpSUdROUlrMHpNVGt1T0RRM0lERTJNUzQxTURKRE16RXdMak0xTmlBeE5qQXVNREEzSURNd01DNDJOelFnTVRZMkxqTXlOaUF5T1RndU1qSXhJREUzTlM0Mk1UWk1NVE00TGpjeU5DQTNOemt1TnpVNFF6RXpOaTR5TnpFZ056ZzVMakEwT0NBeE5ERXVPVGMzSURjNU55NDNPU0F4TlRFdU5EWTRJRGM1T1M0eU9EVk1OelF3TGpBMk1TQTRPVEV1T1RjelF6YzBPUzQxTlRNZ09Ea3pMalEyTnlBM05Ua3VNak0xSURnNE55NHhORGdnTnpZeExqWTROeUE0TnpjdU9EVTRURGt3TWk0ME1EVWdNelEwTGpnMU5FdzRPRGt1TVRVNElETTBNaTQzTmpoTU9EazRMamczTWlBek1EVXVPVGN5VERreE1pNHhNVGtnTXpBNExqQTFPVXc1TVRNdU56TXpJRE13TVM0NU5EWkRPVEUwTGpnek55QXlPVGN1TnpZeUlEa3hOQzR6TURrZ01qa3pMalEzTmlBNU1USXVNalV4SURJNE9TNDVNamRNT0RrekxqUTROQ0F5TlRjdU5UWTVRemc1TVM0eE5UTWdNalV6TGpVME9TQTRPRGN1TURZeklESTFNQzQ0TWpNZ09EZ3lMakl5TVNBeU5UQXVNRFl4VERneU9DNHlNRFVnTWpReExqVTFORU00TWpJdU1qSTBJREkwTUM0Mk1UTWdPREUxTGpnMk9TQXlOREl1TnpneklEZ3hNUzQwTWpjZ01qUTNMakk0TkV3NE1EVXVOamcySURJMU15NHhNRE5ET0RBMExqSXdOU0F5TlRRdU5qQXpJRGd3TWk0d09EY2dNalUxTGpNeU5pQTRNREF1TURreklESTFOUzR3TVROTU56Z3pMall4TVNBeU5USXVOREUzVERjek5DNHpJRFF6T1M0eE9UWkROek14TGpRek9TQTBOVEF1TURNMUlEY3lNQzR4TkRNZ05EVTNMalF3TnlBM01Ea3VNRGNnTkRVMUxqWTJNMHd6TWpndU9EUTNJRE01TlM0M09EaERNekUzTGpjM05DQXpPVFF1TURRMUlETXhNUzR4TVRjZ016Z3pMamcwTlNBek1UTXVPVGM0SURNM015NHdNRGRNTXpZMkxqVXlPQ0F4TnpNdU9UWXlURE0yTmk0MU16TWdNVGN6TGprME1VTXpOamN1TWpNMElERTNNUzR5TkNBek5qVXVOVGN5SURFMk9DNDNNRElnTXpZeUxqZ3hJREUyT0M0eU5qZE1NekU1TGpnME55QXhOakV1TlRBeVdrMHpOamt1TXpreUlERTNOQzQwTVRSTU16WTRMalkxTWlBeE56Y3VNakUzVERNeE5pNDRORE1nTXpjekxqUTFPRU16TVRRdU16a2dNemd5TGpjME9DQXpNakF1TURrMklETTVNUzQwT1NBek1qa3VOVGczSURNNU1pNDVPRFZNTnpBNUxqZ3hJRFExTWk0NE5rTTNNVGt1TXpBeElEUTFOQzR6TlRRZ056STRMams0TXlBME5EZ3VNRE0xSURjek1TNDBNellnTkRNNExqYzBOVXczT0RBdU56UTNJREkxTVM0NU5qWk1Oemd6TGpJME5TQXlOREl1TlRBMFREYzRNeTQ1T0RVZ01qTTVMamN3TVV3ek5qa3VNemt5SURFM05DNDBNVFJhSWlCbWFXeHNQU0oxY213b0kyUnBjMnRsZEhSbExXZHlZV1JwWlc1MEtTSWdabWxzYkMxdmNHRmphWFI1UFNJd0xqSWlJQzgrUEhCaGRHZ2daRDBpVFRNek5TNHpPQ0F5TURndU1URXpRek16TlM0NU1qSWdNakE0TGpFNU9DQXpNell1TkRFM0lESXdOeTQyT0RZZ016TTJMakk0TXlBeU1EY3VNVGM1VERNek1DNHpPU0F4T0RRdU56azFRek16TUM0eU5Ea2dNVGcwTGpJMk1TQXpNamt1TlRJNUlERTROQzR4TkRnZ016STVMakV5T1NBeE9EUXVOVGszVERNeE1pNHpOVGdnTWpBekxqUXhNVU16TVRFdU9UYzRJREl3TXk0NE16Z2dNekV5TGpFM05DQXlNRFF1TkRVNElETXhNaTQzTVRZZ01qQTBMalUwTkV3ek1UY3VPVFl5SURJd05TNHpOME16TVRndU16VTNJREl3TlM0ME16SWdNekU0TGpVNU5TQXlNRFV1TnprMklETXhPQzQwT1RNZ01qQTJMakU0TTB3ek1UUXVOeUF5TWpBdU5UVXhRek14TkM0MU9UY2dNakl3TGprek9DQXpNVFF1T0RNMUlESXlNUzR6TURJZ016RTFMakl6TVNBeU1qRXVNelkwVERNeU5DNDFNemtnTWpJeUxqZ3pRek15TkM0NU16VWdNakl5TGpnNU15QXpNalV1TXpNNElESXlNaTQyTWprZ016STFMalEwSURJeU1pNHlOREpNTXpJNUxqSXpNeUF5TURjdU9EYzFRek15T1M0ek16WWdNakEzTGpRNE9DQXpNamt1TnpNNUlESXdOeTR5TWpRZ016TXdMakV6TlNBeU1EY3VNamcyVERNek5TNHpPQ0F5TURndU1URXpXaUlnWm1sc2JEMGlkWEpzS0NOdFlXbHVLU0lnTHo0OGNHRjBhQ0JrUFNKTk16RTVMakk0TWlBeU5qa3VNRGczUXpNeE9TNDRNalFnTWpZNUxqRTNNeUF6TWpBdU16RTVJREkyT0M0Mk5qRWdNekl3TGpFNE5pQXlOamd1TVRVMFRETXhOQzR5T1RJZ01qUTFMamMzUXpNeE5DNHhOVEVnTWpRMUxqSXpOaUF6TVRNdU5ETXhJREkwTlM0eE1qTWdNekV6TGpBek1TQXlORFV1TlRjeVRESTVOaTR5TmpFZ01qWTBMak00TmtNeU9UVXVPRGdnTWpZMExqZ3hNaUF5T1RZdU1EYzJJREkyTlM0ME16TWdNamsyTGpZeE9DQXlOalV1TlRFNFRETXdNUzQ0TmpRZ01qWTJMak0wTkVNek1ESXVNalU1SURJMk5pNDBNRGNnTXpBeUxqUTVOeUF5TmpZdU56Y3hJRE13TWk0ek9UVWdNalkzTGpFMU9Fd3lPVGd1TmpBeUlESTRNUzQxTWpaRE1qazRMalVnTWpneExqa3hNeUF5T1RndU56TTNJREk0TWk0eU56Y2dNams1TGpFek15QXlPREl1TXpNNVRETXdPQzQwTkRFZ01qZ3pMamd3TlVNek1EZ3VPRE0zSURJNE15NDROamNnTXpBNUxqSTBJREk0TXk0Mk1EUWdNekE1TGpNME15QXlPRE11TWpFM1RETXhNeTR4TXpZZ01qWTRMamcwT1VNek1UTXVNak00SURJMk9DNDBOaklnTXpFekxqWTBNU0F5TmpndU1UazVJRE14TkM0d016Y2dNalk0TGpJMk1Vd3pNVGt1TWpneUlESTJPUzR3T0RkYUlpQm1hV3hzUFNKaWJHRmpheUlnWm1sc2JDMXZjR0ZqYVhSNVBTSXdMalVpSUM4K1BIQmhkR2dnWkQwaVRUTXdNeTR4T0RRZ016TXdMakEyTWtNek1ETXVOekkySURNek1DNHhORGdnTXpBMExqSXlNU0F6TWprdU5qTTJJRE13TkM0d09EZ2dNekk1TGpFeU9Fd3lPVGd1TVRrMElETXdOaTQzTkRWRE1qazRMakExTXlBek1EWXVNakV4SURJNU55NHpNek1nTXpBMkxqQTVPQ0F5T1RZdU9UTXpJRE13Tmk0MU5EZE1Namd3TGpFMk15QXpNalV1TXpZeFF6STNPUzQzT0RJZ016STFMamM0TnlBeU56a3VPVGM1SURNeU5pNDBNRGdnTWpnd0xqVXlJRE15Tmk0ME9UTk1NamcxTGpjMk5pQXpNamN1TXpFNVF6STROaTR4TmpFZ016STNMak00TWlBeU9EWXVNems1SURNeU55NDNORFlnTWpnMkxqSTVOeUF6TWpndU1UTXpUREk0TWk0MU1EUWdNelF5TGpVd01VTXlPREl1TkRBeUlETTBNaTQ0T0RnZ01qZ3lMall6T1NBek5ETXVNalV5SURJNE15NHdNelVnTXpRekxqTXhORXd5T1RJdU16UTBJRE0wTkM0M09FTXlPVEl1TnpNNUlETTBOQzQ0TkRJZ01qa3pMakUwTWlBek5EUXVOVGM1SURJNU15NHlORFVnTXpRMExqRTVNa3d5T1RjdU1ETTRJRE15T1M0NE1qUkRNamszTGpFMElETXlPUzQwTXpjZ01qazNMalUwTXlBek1qa3VNVGMwSURJNU55NDVNemtnTXpJNUxqSXpOa3d6TURNdU1UZzBJRE16TUM0d05qSmFJaUJtYVd4c1BTSmliR0ZqYXlJZ1ptbHNiQzF2Y0dGamFYUjVQU0l3TGpVaUlDOCtQSEJoZEdnZ2MzUnliMnRsUFNKMWNtd29JMjFoYVc0cElpQnpkSEp2YTJVdGQybGtkR2c5SWpZaUlITjBjbTlyWlMxc2FXNWxZMkZ3UFNKeWIzVnVaQ0lnYzNSeWIydGxMV3hwYm1WcWIybHVQU0p5YjNWdVpDSWdaRDBpVFRJNU1DNHhNRGtnTkRZekxqUXhPRU15T1RJdU16VTRJRFExTkM0NU1ESWdNekF4TGpJek15QTBORGt1TVRFZ016QTVMamt6TXlBME5UQXVORGhNTnpjeExqQTNJRFV5TXk0d09UWkROemM1TGpjM0lEVXlOQzQwTmpjZ056ZzFJRFV6TWk0ME9DQTNPREl1TnpVeUlEVTBNQzQ1T1RaTU5qa3lMakE0TmlBNE9EUXVOREU0VERFNU9TNDBORE1nT0RBMkxqZzBUREk1TUM0eE1Ea2dORFl6TGpReE9Gb2lJR1pwYkd3OUltSnNZV05ySWlCbWFXeHNMVzl3WVdOcGRIazlJakF1TVRRaUlDOCtQSEJoZEdnZ1ptbHNiQzF5ZFd4bFBTSmxkbVZ1YjJSa0lpQmpiR2x3TFhKMWJHVTlJbVYyWlc1dlpHUWlJSE4wY205clpUMGlkWEpzS0NOdFlXbHVLU0lnYzNSeWIydGxMWGRwWkhSb1BTSTJJaUJ6ZEhKdmEyVXRiR2x1WldOaGNEMGljbTkxYm1RaUlITjBjbTlyWlMxc2FXNWxhbTlwYmowaWNtOTFibVFpSUdROUlrMDNPRGN1TlRnNUlESXpOeTR6TkRsTU5EWXdMak0xTkNBeE9EVXVPREU0VERRd05pNHpNalVnTXprd0xqUTJPVU0wTURNdU9EY3lJRE01T1M0M05Ua2dOREE1TGpVM09DQTBNRGd1TlRBeElEUXhPUzR3TmprZ05EQTVMams1Tmt3M01URXVPVE0wSURRMU5pNHhNVFJETnpJeExqUXlOU0EwTlRjdU5qQTVJRGN6TVM0eE1EY2dORFV4TGpJNUlEY3pNeTQxTmlBME5ESk1OemczTGpVNE9TQXlNemN1TXpRNVdrMDJOakF1TWpZNUlESTBOUzR3TVVNMk5UVXVOVEl6SURJME5DNHlOak1nTmpVd0xqWTRNaUF5TkRjdU5ESXpJRFkwT1M0ME5UWWdNalV5TGpBMk9FdzJNRGN1TXpnMklEUXhNUzQwTVRoRE5qQTJMakUySURReE5pNHdOak1nTmpBNUxqQXhNeUEwTWpBdU5ETTBJRFl4TXk0M05Ua2dOREl4TGpFNE1VdzJPREl1TkRrNUlEUXpNaTR3TURaRE5qZzNMakkwTlNBME16SXVOelV6SURZNU1pNHdPRFlnTkRJNUxqVTVOQ0EyT1RNdU16RXlJRFF5TkM0NU5EbE1Oek0xTGpNNE1pQXlOalV1TlRrNVF6Y3pOaTQyTURnZ01qWXdMamsxTkNBM016TXVOelUxSURJMU5pNDFPRE1nTnpJNUxqQXhJREkxTlM0NE16Vk1Oall3TGpJMk9TQXlORFV1TURGYUlpQm1hV3hzUFNKMWNtd29JMjFoYVc0cElpQXZQanh3WVhSb0lHWnBiR3d0Y25Wc1pUMGlaWFpsYm05a1pDSWdZMnhwY0MxeWRXeGxQU0psZG1WdWIyUmtJaUJrUFNKTk9EWTBMalkwTXlBeU9ETXVPVE0zUXpnMk5TNHhPRFlnTWpnekxqWXdOU0E0TmpVdU56QTRJREk0TkM0eU5UY2dPRFkxTGpJek9TQXlPRFF1TmpnelREZzBOQzR5TmpnZ016QXpMamN4T1VNNE5ETXVPVE00SURNd05DNHdNVGdnT0RRMExqQTVNeUF6TURRdU5URTNJRGcwTkM0MU1qWWdNekEwTGpVME9FdzROVE11TnpJMklETXdOUzR5TURkRE9EVTBMakU0TkNBek1EVXVNalFnT0RVMExqTXlNU0F6TURVdU56ZzNJRGcxTXk0NU5ESWdNekEyTGpBM01VdzRNek11T0RnMElETXlNUzR4TVRKRE9ETXpMalV3TmlBek1qRXVNemsySURnek15NDJORE1nTXpJeExqazBNeUE0TXpRdU1UQXhJRE15TVM0NU56Wk1PRFEwTGpBd055QXpNakl1TmpnMVF6ZzBOQzQwT1RFZ016SXlMamN5SURnME5DNDJNRFVnTXpJekxqTXhPU0E0TkRRdU1UYzNJRE15TXk0MU9FdzNPVGN1TnpVeUlETTFNUzQ1TlRSRE56azNMakl3T1NBek5USXVNamcySURjNU5pNDJPRGNnTXpVeExqWXpOQ0EzT1RjdU1UVTJJRE0xTVM0eU1EbE1PREU0TGpRd015QXpNekV1T1RJeVF6Z3hPQzQzTXpNZ016TXhMall5TWlBNE1UZ3VOVGMzSURNek1TNHhNak1nT0RFNExqRTBOU0F6TXpFdU1Ea3lURGd3T0M0M05EZ2dNek13TGpReVF6Z3dPQzR5T1RJZ016TXdMak00TnlBNE1EZ3VNVFUwSURNeU9TNDRORE1nT0RBNExqVXlPU0F6TWprdU5UVTRURGd5T0M0d05UUWdNekUwTGpjME5FTTRNamd1TkRNZ016RTBMalExT1NBNE1qZ3VNamt4SURNeE15NDVNVFVnT0RJM0xqZ3pOU0F6TVRNdU9EZ3lURGd4T0M0ek9Ea2dNekV6TGpJd05rTTRNVGN1T1RBMElETXhNeTR4TnpFZ09ERTNMamM1SURNeE1pNDFOeklnT0RFNExqSXhPQ0F6TVRJdU16RXhURGcyTkM0Mk5ETWdNamd6TGprek4xb2lJR1pwYkd3OUluZG9hWFJsSWlBdlBqeG5JSFJ5WVc1elptOXliVDBpYldGMGNtbDRLREF1T1RnM09ESTNJREF1TVRVMU5UVTNJQzB3TGpJMU5USTJNU0F3TGprMk5qZzNNaUF5TlRBZ056TTFLU0krUEhSbGVIUWdabTl1ZEMxbVlXMXBiSGs5SWtsdWRHVnlMQ0J6WVc1ekxYTmxjbWxtSWlCbWIyNTBMWGRsYVdkb2REMGlZbTlzWkNJZ1ptOXVkQzF6YVhwbFBTSTBNaUlnWm1sc2JEMGlJMFUxUlRkR09DSStUbVYzSUVGd2NDQk9ZVzFsUEM5MFpYaDBQangwWlhoMElHWnZiblF0Wm1GdGFXeDVQU0pKYm5SbGNpd2djMkZ1Y3kxelpYSnBaaUlnWm05dWRDMTNaV2xuYUhROUltNXZjbTFoYkNJZ2VUMGlOREFpSUdadmJuUXRjMmw2WlQwaU1qSWlJR1pwYkd3OUlpTTNSamd4T1RJaVBtNWxkeTFsYm5NdVpYUm9QQzkwWlhoMFBqd3ZaejQ4YVcxaFoyVWdkMmxrZEdnOUlqRTJOeUlnYUdWcFoyaDBQU0l4TmpjaUlIUnlZVzV6Wm05eWJUMGliV0YwY21sNEtEQXVPVGczT0RJM0lEQXVNVFUxTlRVM0lDMHdMakkxTlRJMk1TQXdMamsyTmpnM01pQTBORFF1TVRFM0lEVXlOQzR4TnlraUlHaHlaV1k5SW1SaGRHRTZhVzFoWjJVdmMzWm5LM2h0YkR0aVlYTmxOalFzVUVoT01scDVRakphV0VwNllWYzVkVkJUU1hoTWFrVnBTVWhvZEdKSE5YcFFVMHB2WkVoU2QwOXBPSFprTTJRelRHNWpla3h0T1hsYWVUaDVUVVJCZDB3elRqSmFlVWxuWlVjeGMySnVUVFpsUjNod1ltMXpPVWx0YURCa1NFRTJUSGs1TTJRelkzVmtlazExWWpOS2JreDZSVFZQVkd0MlpVZDRjR0p0YzJsSlNHYzVTV3BDZDJWRFNXZGxWREJwVFVoQ05FbHBRakpoVjFZelVXMDVORkJUU1hkSlJFRm5UVlJCZDAxRFFYaE5SRUYzU1dsQ2JHSnRSbWxpUjFWMFdXMUdhbUV5WkhsaU0xWjFXa1F3YVdKdFZqTkpSRUZuVFVOQmVFMUVRWGRKUkVWM1RVUkJhVWxJYUhSaVJIQjZZMGRHYWxwVU1HbGpTRXBzWXpKV2VXUnRWV2xRWjI4NFdubzBPR05IUmpCaFEwSnJVRk5LVGs1VVFYZE1SRVYzVVhwSmVVOVROREJNUkVWM1RFUkZkMHhFU1hsUFV6UXdURVJGZDB4RVZYZE5SMDEzVEVSSk0wMUROREpNUkVsNFQxTTBNRXhFVVRWTlEzY3dUMVJCYzA1RWEzZFpla2t6VFVNME1reEVRWE5PUkd0M1RGUkplRTlUTkRCTVJGRTFUVU13TUU5VVFrUlBWR3QzVEVSSmVVOVROREJNUkdNelRVTTBNa3hFUlhkTVJGVjNUVU4zZUUxSWIyZFVWR2Q0VGxOM05FMVVWbXBNVkZGM1RHcHJjMDVFUVhWUFV6QTBUME0wTWt4RVkzcE1ha1YwVFZSUmVFeHFXWE5QVkZWMVRsZE5kRTVVVVhWUFUzZDVUWGswZVV4VVJYaE5lVFI1VEVSTk1VeFVSVE5OZVRRd1RFUk5NVmw1TURKTlF6UjVURVJCZEUxVVJUUk1hbFYwVFZSRmRVOURNSGhPZWsxMVRrTXdlazVWVFhsT2VrMTFUbWwzTkU5RVozTk5ha2t4VEdwcmMwOUVWVEZNYW10elRWUm5NVXhFWjNoT1dFMTBUbnBOZEU5RVozVk9hVEExVGxNME1VeFVSVEJOVXpReVdYa3dlVTE1TkhsTVZGVXdUR3ByZEUxNlZYUk5WRVY2VEdwSmRFMTZWWFJOVkdONlRHcFNhazFETURKTlF6UjVURVJGZUV4cVozUk5WRVUwVEdwVmMwMTZWWFJOVkdONlRHcFNhazFxU1hWT1F6QXhUWGwzTVU1RE5ESk1WRVYzVFVNME0weEVhekZNYWxWMFRWUlJlRXhxV25wUFJHZDFUbWt3TTAxNWQzaE9SRVYxVG1rd05VNVROREZaZWxVd1RHcHJkRTFxVFhWTmFYZDRUVlJOZFUxcE1IcE9VM2Q0VG5wTmRVNURNSHBPVjAweVRVTTBlVXhFUVhOTlZFVTBUR3BWYzAxVVJYVlBRM2Q0VG5wTmRVNURkM3BPVjAweFRYbDNlVTFwTkRCTVJFVjNUVU0wTTB4RVZUQk1hbGx6VFZSUmVFeHFXWE5QVkZWMVRsZE5NRTFETkRWTVJGRjNUR3ByYzA1NlRYTlBSR2QxVG1sM05VNVROREZNUkVVd1RWTTBNbGw2U1hwTWFrbHpUbFJSZFU5VGQzcE9VM2Q0VFZSTmRVMXBkM3BPVTNkNFRucE5kVTVIVFhkTVJGbDNUR3BKZEUxVVJYVlBRM2Q0VFZSbmRVNVRNSHBPVTNkNFRucE5kVTVGVFRSUFJHZHpUbnBKTWt4cVVYTlBSRlV4VEdwcmMwNTZZekJNYWtWelQwUkZNVXhFWjNoT1dHOXBUSG8wT0V3eVl5dERhbmQyWXpOYWJsQm5QVDBpSUM4K1BHUmxabk0rUEdacGJIUmxjaUJwWkQwaVpHbHphMlYwZEdVdGMyaGhaRzkzSWlCNFBTSTNNQzQzTkRnNUlpQjVQU0l4T1RVdU56RXlJaUIzYVdSMGFEMGlPVFUxTGpjek15SWdhR1ZwWjJoMFBTSTRNekl1TlRVNElpQm1hV3gwWlhKVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR052Ykc5eUxXbHVkR1Z5Y0c5c1lYUnBiMjR0Wm1sc2RHVnljejBpYzFKSFFpSStQR1psUm14dmIyUWdabXh2YjJRdGIzQmhZMmwwZVQwaU1DSWdMejQ4Wm1WQ2JHVnVaQ0JwYmowaVUyOTFjbU5sUjNKaGNHaHBZeUlnTHo0OFptVkhZWFZ6YzJsaGJrSnNkWElnYzNSa1JHVjJhV0YwYVc5dVBTSTBNaUlnTHo0OEwyWnBiSFJsY2o0OGJHbHVaV0Z5UjNKaFpHbGxiblFnYVdROUltSmhZMnRuY205MWJtUWlJSGd4UFNJMU16SXVOU0lnZVRFOUlqQWlJSGd5UFNJMU16SXVOU0lnZVRJOUlqRXdOalVpSUdkeVlXUnBaVzUwVlc1cGRITTlJblZ6WlhKVGNHRmpaVTl1VlhObElqNDhjM1J2Y0NBdlBqeHpkRzl3SUc5bVpuTmxkRDBpTVNJZ2MzUnZjQzFqYjJ4dmNqMGlJekV6TVRNeE15SWdMejQ4TDJ4cGJtVmhja2R5WVdScFpXNTBQanh5WVdScFlXeEhjbUZrYVdWdWRDQnBaRDBpWW1GamEyZHliM1Z1WkMxeVlXUnBZV3dpSUdONFBTSXdJaUJqZVQwaU1DSWdjajBpTVNJZ1ozSmhaR2xsYm5SVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR2R5WVdScFpXNTBWSEpoYm5ObWIzSnRQU0owY21GdWMyeGhkR1VvTlRNeUxqVWdOVE15TGpVcElISnZkR0YwWlNnNE9TNDVOakVwSUhOallXeGxLRGN6TlNraVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTTJOVFF6TWpFaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTmpVME16SXhJaUJ6ZEc5d0xXOXdZV05wZEhrOUlqQWlJQzgrUEM5eVlXUnBZV3hIY21Ga2FXVnVkRDQ4YkdsdVpXRnlSM0poWkdsbGJuUWdhV1E5SW1ScGMydGxkSFJsTFdkeVlXUnBaVzUwSWlCNE1UMGlPVEkxTGpZeU5pSWdlVEU5SWpJMU5pNDRPVFlpSUhneVBTSXhNell1TnpjNUlpQjVNajBpT0RBd0xqSXdNeUlnWjNKaFpHbGxiblJWYm1sMGN6MGlkWE5sY2xOd1lXTmxUMjVWYzJVaVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTTJOVFF6TWpFaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTWtNek1UTkdJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEd4cGJtVmhja2R5WVdScFpXNTBJR2xrUFNKdFlXbHVJajQ4YzNSdmNDQnpkRzl3TFdOdmJHOXlQU0lqTmpVME16SXhJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEM5a1pXWnpQand2YzNablBnPT0iLCJhY2Nlc3NfcG9pbnRfYXV0b19hcHByb3ZhbCI6ZmFsc2UsInZlcmlmaWVkIjp0cnVlLCJhdHRyaWJ1dGVzIjogW3sidHJhaXRfdHlwZSI6ICJFTlMiLCAidmFsdWUiOiJuZXctZW5zLmV0aCJ9LHsidHJhaXRfdHlwZSI6ICJDb21taXQgSGFzaCIsICJ2YWx1ZSI6ImNlMWEzZmMxNDFlMjlmOGUxZDAwYTY1NGUxNTZjNDk4MmQ3NzExYmYifSx7InRyYWl0X3R5cGUiOiAiUmVwb3NpdG9yeSIsICJ2YWx1ZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9vdGhlci9yZXBvIn0seyJ0cmFpdF90eXBlIjogIlZlcnNpb24iLCAidmFsdWUiOiIxIn0seyJ0cmFpdF90eXBlIjogIkNvbG9yIiwgInZhbHVlIjoiIzY1NDMyMSJ9XX0=" + "data:application/json;base64,eyJuYW1lIjoiTmV3IEFwcCBOYW1lIiwiZGVzY3JpcHRpb24iOiJOZXcgZGVzY3JpcHRpb24gZm9yIHRoZSBhcHAuIiwib3duZXIiOiIweDkwMTkzYzk2MWE5MjYyNjFiNzU2ZDFlNWJiMjU1ZTY3ZmY5NDk4YTEiLCJleHRlcm5hbF91cmwiOiJodHRwczovL25ldy11cmwuY29tIiwiaW1hZ2UiOiJkYXRhOmltYWdlL3N2Zyt4bWw7YmFzZTY0LFBITjJaeUIzYVdSMGFEMGlNVEEyTlNJZ2FHVnBaMmgwUFNJeE1EWTFJaUIyYVdWM1FtOTRQU0l3SURBZ01UQTJOU0F4TURZMUlpQm1hV3hzUFNKdWIyNWxJaUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSGh0Ykc1ek9uaHNhVzVyUFNKb2RIUndPaTh2ZDNkM0xuY3pMbTl5Wnk4eE9UazVMM2hzYVc1cklqNDhjM1I1YkdVZ2RIbHdaVDBpZEdWNGRDOWpjM01pUGtCcGJYQnZjblFnZFhKc0tDSm9kSFJ3Y3pvdkwyWnZiblJ6TG1kdmIyZHNaV0Z3YVhNdVkyOXRMMk56Y3pJL1ptRnRhV3g1UFVsdWRHVnlPbmRuYUhSQU5UQXdPell3TUNJcE96d3ZjM1I1YkdVK1BISmxZM1FnZDJsa2RHZzlJakV3TmpVaUlHaGxhV2RvZEQwaU1UQTJOU0lnWm1sc2JEMGlkWEpzS0NOaVlXTnJaM0p2ZFc1a0tTSWdMejQ4Y21WamRDQnZjR0ZqYVhSNVBTSXdMaklpSUhkcFpIUm9QU0l4TURZMUlpQm9aV2xuYUhROUlqRXdOalVpSUdacGJHdzlJblZ5YkNnalltRmphMmR5YjNWdVpDMXlZV1JwWVd3cElpQXZQanhuSUdacGJIUmxjajBpZFhKc0tDTmthWE5yWlhSMFpTMXphR0ZrYjNjcElqNDhjR0YwYUNCa1BTSk5PRFUzTGpJek1TQXlOemt1TnpFeVREa3dNaTR5TkNBeU9EWXVOamMxUXpreE1DNDFORGNnTWpnM0xqazJJRGt4Tnk0NU1UVWdNamt5TGpjeU1TQTVNakl1TlNBeU9Ua3VOelk0VERrek9DNDRPVFFnTXpJMExqazJORU01TkRJdU1qUTVJRE16TUM0eE1pQTVORE11TXpFeElETXpOaTQwTXpjZ09UUXhMamd5TnlBek5ESXVOREEyVERrek55NDNPVGdnTXpVNExqWXhOVXc1TWpRdU1EUTVJRE0xTmk0Mk5VdzVNVGt1TkRFMklETTNOQzR3T0RSTU9UTTBMakEyT0NBek56WXVNalJNTnpreExqazBOeUE1TWpJdU1UVXlRemM0T0M0eE1Ea2dPVE0yTGpnNU5pQTNOek11TmprMElEazBOaTR6TURnZ056VTRMalkxTVNBNU5ETXVPRGt6VERFM09TNDJNellnT0RVd0xqa3lPRU14TmpJdU16RTRJRGcwT0M0eE5EY2dNVFV4TGpJeE5TQTRNekF1T1RnM0lERTFOUzQzTnpZZ09ERTBMakExTVV3eE5qQXVORGM0SURjNU5pNDFPVXczTURRdU16RTFJRGczT1M0MU56Uk1PRFUzTGpJek1TQXlOemt1TnpFeVdpSWdabWxzYkQwaUl6QTFNRFV3TlNJZ0x6NDhMMmMrUEhCaGRHZ2daRDBpVFRnME1DNHlNekVnTWpRd0xqY3hNa3c0T0RVdU1qUWdNalEzTGpZM05VTTRPVE11TlRRM0lESTBPQzQ1TmpFZ09UQXdMamt4TlNBeU5UTXVOekl5SURrd05TNDFJREkyTUM0M05qaE1PVEl4TGpnNU5DQXlPRFV1T1RZMVF6a3lOUzR5TkRrZ01qa3hMakV5SURreU5pNHpNVEVnTWprM0xqUXpOeUE1TWpRdU9ESTNJRE13TXk0ME1EWk1PVEl3TGpjNU9DQXpNVGt1TmpFMlREa3dOeTR3TkRrZ016RTNMalkxVERrd01pNDBNVFlnTXpNMUxqQTRORXc1TVRjdU1EWTRJRE16Tnk0eU5ERk1OemMwTGprME55QTRPRE11TVRVeVF6YzNNUzR4TURrZ09EazNMamc1TmlBM05UWXVOamswSURrd055NHpNRGdnTnpReExqWTFNU0E1TURRdU9Ea3pUREUyTWk0Mk16WWdPREV4TGpreU9FTXhORFV1TXpFNElEZ3dPUzR4TkRjZ01UTTBMakl4TlNBM09URXVPVGczSURFek9DNDNOellnTnpjMUxqQTFNVXd4TkRNdU5EYzRJRGMxTnk0MU9VdzJPRGN1TXpFMUlEZzBNQzQxTnpSTU9EUXdMakl6TVNBeU5EQXVOekV5V2lJZ1ptbHNiRDBpZFhKc0tDTnRZV2x1S1NJZ0x6NDhjR0YwYUNCbWFXeHNMWEoxYkdVOUltVjJaVzV2WkdRaUlHTnNhWEF0Y25Wc1pUMGlaWFpsYm05a1pDSWdaRDBpVFRNeE9TNDRORGNnTVRZeExqVXdNa016TVRBdU16VTJJREUyTUM0d01EY2dNekF3TGpZM05DQXhOall1TXpJMklESTVPQzR5TWpFZ01UYzFMall4Tmt3eE16Z3VOekkwSURjM09TNDNOVGhETVRNMkxqSTNNU0EzT0RrdU1EUTRJREUwTVM0NU56Y2dOemszTGpjNUlERTFNUzQwTmpnZ056azVMakk0TlV3M05EQXVNRFl4SURnNU1TNDVOek5ETnpRNUxqVTFNeUE0T1RNdU5EWTNJRGMxT1M0eU16VWdPRGczTGpFME9DQTNOakV1TmpnM0lEZzNOeTQ0TlRoTU9UQXlMalF3TlNBek5EUXVPRFUwVERnNE9TNHhOVGdnTXpReUxqYzJPRXc0T1RndU9EY3lJRE13TlM0NU56Sk1PVEV5TGpFeE9TQXpNRGd1TURVNVREa3hNeTQzTXpNZ016QXhMamswTmtNNU1UUXVPRE0zSURJNU55NDNOaklnT1RFMExqTXdPU0F5T1RNdU5EYzJJRGt4TWk0eU5URWdNamc1TGpreU4wdzRPVE11TkRnMElESTFOeTQxTmpsRE9Ea3hMakUxTXlBeU5UTXVOVFE1SURnNE55NHdOak1nTWpVd0xqZ3lNeUE0T0RJdU1qSXhJREkxTUM0d05qRk1PREk0TGpJd05TQXlOREV1TlRVMFF6Z3lNaTR5TWpRZ01qUXdMall4TXlBNE1UVXVPRFk1SURJME1pNDNPRE1nT0RFeExqUXlOeUF5TkRjdU1qZzBURGd3TlM0Mk9EWWdNalV6TGpFd00wTTRNRFF1TWpBMUlESTFOQzQyTURNZ09EQXlMakE0TnlBeU5UVXVNekkySURnd01DNHdPVE1nTWpVMUxqQXhNMHczT0RNdU5qRXhJREkxTWk0ME1UZE1Oek0wTGpNZ05ETTVMakU1TmtNM016RXVORE01SURRMU1DNHdNelVnTnpJd0xqRTBNeUEwTlRjdU5EQTNJRGN3T1M0d055QTBOVFV1TmpZelRETXlPQzQ0TkRjZ016azFMamM0T0VNek1UY3VOemMwSURNNU5DNHdORFVnTXpFeExqRXhOeUF6T0RNdU9EUTFJRE14TXk0NU56Z2dNemN6TGpBd04wd3pOall1TlRJNElERTNNeTQ1TmpKTU16WTJMalV6TXlBeE56TXVPVFF4UXpNMk55NHlNelFnTVRjeExqSTBJRE0yTlM0MU56SWdNVFk0TGpjd01pQXpOakl1T0RFZ01UWTRMakkyTjB3ek1Ua3VPRFEzSURFMk1TNDFNREphVFRNMk9TNHpPVElnTVRjMExqUXhORXd6TmpndU5qVXlJREUzTnk0eU1UZE1NekUyTGpnME15QXpOek11TkRVNFF6TXhOQzR6T1NBek9ESXVOelE0SURNeU1DNHdPVFlnTXpreExqUTVJRE15T1M0MU9EY2dNemt5TGprNE5VdzNNRGt1T0RFZ05EVXlMamcyUXpjeE9TNHpNREVnTkRVMExqTTFOQ0EzTWpndU9UZ3pJRFEwT0M0d016VWdOek14TGpRek5pQTBNemd1TnpRMVREYzRNQzQzTkRjZ01qVXhMamsyTmt3M09ETXVNalExSURJME1pNDFNRFJNTnpnekxqazROU0F5TXprdU56QXhURE0yT1M0ek9USWdNVGMwTGpReE5Gb2lJR1pwYkd3OUlpTXhNekV6TVRZaUlDOCtQSEJoZEdnZ1ptbHNiQzF5ZFd4bFBTSmxkbVZ1YjJSa0lpQmpiR2x3TFhKMWJHVTlJbVYyWlc1dlpHUWlJSE4wY205clpUMGlkWEpzS0NOdFlXbHVLU0lnYzNSeWIydGxMWGRwWkhSb1BTSTBJaUJ6ZEhKdmEyVXRiR2x1WldOaGNEMGljbTkxYm1RaUlITjBjbTlyWlMxc2FXNWxhbTlwYmowaWNtOTFibVFpSUdROUlrMHpNVGt1T0RRM0lERTJNUzQxTURKRE16RXdMak0xTmlBeE5qQXVNREEzSURNd01DNDJOelFnTVRZMkxqTXlOaUF5T1RndU1qSXhJREUzTlM0Mk1UWk1NVE00TGpjeU5DQTNOemt1TnpVNFF6RXpOaTR5TnpFZ056ZzVMakEwT0NBeE5ERXVPVGMzSURjNU55NDNPU0F4TlRFdU5EWTRJRGM1T1M0eU9EVk1OelF3TGpBMk1TQTRPVEV1T1RjelF6YzBPUzQxTlRNZ09Ea3pMalEyTnlBM05Ua3VNak0xSURnNE55NHhORGdnTnpZeExqWTROeUE0TnpjdU9EVTRURGt3TWk0ME1EVWdNelEwTGpnMU5FdzRPRGt1TVRVNElETTBNaTQzTmpoTU9EazRMamczTWlBek1EVXVPVGN5VERreE1pNHhNVGtnTXpBNExqQTFPVXc1TVRNdU56TXpJRE13TVM0NU5EWkRPVEUwTGpnek55QXlPVGN1TnpZeUlEa3hOQzR6TURrZ01qa3pMalEzTmlBNU1USXVNalV4SURJNE9TNDVNamRNT0RrekxqUTROQ0F5TlRjdU5UWTVRemc1TVM0eE5UTWdNalV6TGpVME9TQTRPRGN1TURZeklESTFNQzQ0TWpNZ09EZ3lMakl5TVNBeU5UQXVNRFl4VERneU9DNHlNRFVnTWpReExqVTFORU00TWpJdU1qSTBJREkwTUM0Mk1UTWdPREUxTGpnMk9TQXlOREl1TnpneklEZ3hNUzQwTWpjZ01qUTNMakk0TkV3NE1EVXVOamcySURJMU15NHhNRE5ET0RBMExqSXdOU0F5TlRRdU5qQXpJRGd3TWk0d09EY2dNalUxTGpNeU5pQTRNREF1TURreklESTFOUzR3TVROTU56Z3pMall4TVNBeU5USXVOREUzVERjek5DNHpJRFF6T1M0eE9UWkROek14TGpRek9TQTBOVEF1TURNMUlEY3lNQzR4TkRNZ05EVTNMalF3TnlBM01Ea3VNRGNnTkRVMUxqWTJNMHd6TWpndU9EUTNJRE01TlM0M09EaERNekUzTGpjM05DQXpPVFF1TURRMUlETXhNUzR4TVRjZ016Z3pMamcwTlNBek1UTXVPVGM0SURNM015NHdNRGRNTXpZMkxqVXlPQ0F4TnpNdU9UWXlURE0yTmk0MU16TWdNVGN6TGprME1VTXpOamN1TWpNMElERTNNUzR5TkNBek5qVXVOVGN5SURFMk9DNDNNRElnTXpZeUxqZ3hJREUyT0M0eU5qZE1NekU1TGpnME55QXhOakV1TlRBeVdrMHpOamt1TXpreUlERTNOQzQwTVRSTU16WTRMalkxTWlBeE56Y3VNakUzVERNeE5pNDRORE1nTXpjekxqUTFPRU16TVRRdU16a2dNemd5TGpjME9DQXpNakF1TURrMklETTVNUzQwT1NBek1qa3VOVGczSURNNU1pNDVPRFZNTnpBNUxqZ3hJRFExTWk0NE5rTTNNVGt1TXpBeElEUTFOQzR6TlRRZ056STRMams0TXlBME5EZ3VNRE0xSURjek1TNDBNellnTkRNNExqYzBOVXczT0RBdU56UTNJREkxTVM0NU5qWk1Oemd6TGpJME5TQXlOREl1TlRBMFREYzRNeTQ1T0RVZ01qTTVMamN3TVV3ek5qa3VNemt5SURFM05DNDBNVFJhSWlCbWFXeHNQU0oxY213b0kyUnBjMnRsZEhSbExXZHlZV1JwWlc1MEtTSWdabWxzYkMxdmNHRmphWFI1UFNJd0xqSWlJQzgrUEhCaGRHZ2daRDBpVFRNek5TNHpPQ0F5TURndU1URXpRek16TlM0NU1qSWdNakE0TGpFNU9DQXpNell1TkRFM0lESXdOeTQyT0RZZ016TTJMakk0TXlBeU1EY3VNVGM1VERNek1DNHpPU0F4T0RRdU56azFRek16TUM0eU5Ea2dNVGcwTGpJMk1TQXpNamt1TlRJNUlERTROQzR4TkRnZ016STVMakV5T1NBeE9EUXVOVGszVERNeE1pNHpOVGdnTWpBekxqUXhNVU16TVRFdU9UYzRJREl3TXk0NE16Z2dNekV5TGpFM05DQXlNRFF1TkRVNElETXhNaTQzTVRZZ01qQTBMalUwTkV3ek1UY3VPVFl5SURJd05TNHpOME16TVRndU16VTNJREl3TlM0ME16SWdNekU0TGpVNU5TQXlNRFV1TnprMklETXhPQzQwT1RNZ01qQTJMakU0TTB3ek1UUXVOeUF5TWpBdU5UVXhRek14TkM0MU9UY2dNakl3TGprek9DQXpNVFF1T0RNMUlESXlNUzR6TURJZ016RTFMakl6TVNBeU1qRXVNelkwVERNeU5DNDFNemtnTWpJeUxqZ3pRek15TkM0NU16VWdNakl5TGpnNU15QXpNalV1TXpNNElESXlNaTQyTWprZ016STFMalEwSURJeU1pNHlOREpNTXpJNUxqSXpNeUF5TURjdU9EYzFRek15T1M0ek16WWdNakEzTGpRNE9DQXpNamt1TnpNNUlESXdOeTR5TWpRZ016TXdMakV6TlNBeU1EY3VNamcyVERNek5TNHpPQ0F5TURndU1URXpXaUlnWm1sc2JEMGlkWEpzS0NOdFlXbHVLU0lnTHo0OGNHRjBhQ0JrUFNKTk16RTVMakk0TWlBeU5qa3VNRGczUXpNeE9TNDRNalFnTWpZNUxqRTNNeUF6TWpBdU16RTVJREkyT0M0Mk5qRWdNekl3TGpFNE5pQXlOamd1TVRVMFRETXhOQzR5T1RJZ01qUTFMamMzUXpNeE5DNHhOVEVnTWpRMUxqSXpOaUF6TVRNdU5ETXhJREkwTlM0eE1qTWdNekV6TGpBek1TQXlORFV1TlRjeVRESTVOaTR5TmpFZ01qWTBMak00TmtNeU9UVXVPRGdnTWpZMExqZ3hNaUF5T1RZdU1EYzJJREkyTlM0ME16TWdNamsyTGpZeE9DQXlOalV1TlRFNFRETXdNUzQ0TmpRZ01qWTJMak0wTkVNek1ESXVNalU1SURJMk5pNDBNRGNnTXpBeUxqUTVOeUF5TmpZdU56Y3hJRE13TWk0ek9UVWdNalkzTGpFMU9Fd3lPVGd1TmpBeUlESTRNUzQxTWpaRE1qazRMalVnTWpneExqa3hNeUF5T1RndU56TTNJREk0TWk0eU56Y2dNams1TGpFek15QXlPREl1TXpNNVRETXdPQzQwTkRFZ01qZ3pMamd3TlVNek1EZ3VPRE0zSURJNE15NDROamNnTXpBNUxqSTBJREk0TXk0Mk1EUWdNekE1TGpNME15QXlPRE11TWpFM1RETXhNeTR4TXpZZ01qWTRMamcwT1VNek1UTXVNak00SURJMk9DNDBOaklnTXpFekxqWTBNU0F5TmpndU1UazVJRE14TkM0d016Y2dNalk0TGpJMk1Vd3pNVGt1TWpneUlESTJPUzR3T0RkYUlpQm1hV3hzUFNKaWJHRmpheUlnWm1sc2JDMXZjR0ZqYVhSNVBTSXdMalVpSUM4K1BIQmhkR2dnWkQwaVRUTXdNeTR4T0RRZ016TXdMakEyTWtNek1ETXVOekkySURNek1DNHhORGdnTXpBMExqSXlNU0F6TWprdU5qTTJJRE13TkM0d09EZ2dNekk1TGpFeU9Fd3lPVGd1TVRrMElETXdOaTQzTkRWRE1qazRMakExTXlBek1EWXVNakV4SURJNU55NHpNek1nTXpBMkxqQTVPQ0F5T1RZdU9UTXpJRE13Tmk0MU5EZE1Namd3TGpFMk15QXpNalV1TXpZeFF6STNPUzQzT0RJZ016STFMamM0TnlBeU56a3VPVGM1SURNeU5pNDBNRGdnTWpnd0xqVXlJRE15Tmk0ME9UTk1NamcxTGpjMk5pQXpNamN1TXpFNVF6STROaTR4TmpFZ016STNMak00TWlBeU9EWXVNems1SURNeU55NDNORFlnTWpnMkxqSTVOeUF6TWpndU1UTXpUREk0TWk0MU1EUWdNelF5TGpVd01VTXlPREl1TkRBeUlETTBNaTQ0T0RnZ01qZ3lMall6T1NBek5ETXVNalV5SURJNE15NHdNelVnTXpRekxqTXhORXd5T1RJdU16UTBJRE0wTkM0M09FTXlPVEl1TnpNNUlETTBOQzQ0TkRJZ01qa3pMakUwTWlBek5EUXVOVGM1SURJNU15NHlORFVnTXpRMExqRTVNa3d5T1RjdU1ETTRJRE15T1M0NE1qUkRNamszTGpFMElETXlPUzQwTXpjZ01qazNMalUwTXlBek1qa3VNVGMwSURJNU55NDVNemtnTXpJNUxqSXpOa3d6TURNdU1UZzBJRE16TUM0d05qSmFJaUJtYVd4c1BTSmliR0ZqYXlJZ1ptbHNiQzF2Y0dGamFYUjVQU0l3TGpVaUlDOCtQSEJoZEdnZ2MzUnliMnRsUFNKMWNtd29JMjFoYVc0cElpQnpkSEp2YTJVdGQybGtkR2c5SWpZaUlITjBjbTlyWlMxc2FXNWxZMkZ3UFNKeWIzVnVaQ0lnYzNSeWIydGxMV3hwYm1WcWIybHVQU0p5YjNWdVpDSWdaRDBpVFRJNU1DNHhNRGtnTkRZekxqUXhPRU15T1RJdU16VTRJRFExTkM0NU1ESWdNekF4TGpJek15QTBORGt1TVRFZ016QTVMamt6TXlBME5UQXVORGhNTnpjeExqQTNJRFV5TXk0d09UWkROemM1TGpjM0lEVXlOQzQwTmpjZ056ZzFJRFV6TWk0ME9DQTNPREl1TnpVeUlEVTBNQzQ1T1RaTU5qa3lMakE0TmlBNE9EUXVOREU0VERFNU9TNDBORE1nT0RBMkxqZzBUREk1TUM0eE1Ea2dORFl6TGpReE9Gb2lJR1pwYkd3OUltSnNZV05ySWlCbWFXeHNMVzl3WVdOcGRIazlJakF1TVRRaUlDOCtQSEJoZEdnZ1ptbHNiQzF5ZFd4bFBTSmxkbVZ1YjJSa0lpQmpiR2x3TFhKMWJHVTlJbVYyWlc1dlpHUWlJSE4wY205clpUMGlkWEpzS0NOdFlXbHVLU0lnYzNSeWIydGxMWGRwWkhSb1BTSTJJaUJ6ZEhKdmEyVXRiR2x1WldOaGNEMGljbTkxYm1RaUlITjBjbTlyWlMxc2FXNWxhbTlwYmowaWNtOTFibVFpSUdROUlrMDNPRGN1TlRnNUlESXpOeTR6TkRsTU5EWXdMak0xTkNBeE9EVXVPREU0VERRd05pNHpNalVnTXprd0xqUTJPVU0wTURNdU9EY3lJRE01T1M0M05Ua2dOREE1TGpVM09DQTBNRGd1TlRBeElEUXhPUzR3TmprZ05EQTVMams1Tmt3M01URXVPVE0wSURRMU5pNHhNVFJETnpJeExqUXlOU0EwTlRjdU5qQTVJRGN6TVM0eE1EY2dORFV4TGpJNUlEY3pNeTQxTmlBME5ESk1OemczTGpVNE9TQXlNemN1TXpRNVdrMDJOakF1TWpZNUlESTBOUzR3TVVNMk5UVXVOVEl6SURJME5DNHlOak1nTmpVd0xqWTRNaUF5TkRjdU5ESXpJRFkwT1M0ME5UWWdNalV5TGpBMk9FdzJNRGN1TXpnMklEUXhNUzQwTVRoRE5qQTJMakUySURReE5pNHdOak1nTmpBNUxqQXhNeUEwTWpBdU5ETTBJRFl4TXk0M05Ua2dOREl4TGpFNE1VdzJPREl1TkRrNUlEUXpNaTR3TURaRE5qZzNMakkwTlNBME16SXVOelV6SURZNU1pNHdPRFlnTkRJNUxqVTVOQ0EyT1RNdU16RXlJRFF5TkM0NU5EbE1Oek0xTGpNNE1pQXlOalV1TlRrNVF6Y3pOaTQyTURnZ01qWXdMamsxTkNBM016TXVOelUxSURJMU5pNDFPRE1nTnpJNUxqQXhJREkxTlM0NE16Vk1Oall3TGpJMk9TQXlORFV1TURGYUlpQm1hV3hzUFNKMWNtd29JMjFoYVc0cElpQXZQanh3WVhSb0lHWnBiR3d0Y25Wc1pUMGlaWFpsYm05a1pDSWdZMnhwY0MxeWRXeGxQU0psZG1WdWIyUmtJaUJrUFNKTk9EWTBMalkwTXlBeU9ETXVPVE0zUXpnMk5TNHhPRFlnTWpnekxqWXdOU0E0TmpVdU56QTRJREk0TkM0eU5UY2dPRFkxTGpJek9TQXlPRFF1TmpnelREZzBOQzR5TmpnZ016QXpMamN4T1VNNE5ETXVPVE00SURNd05DNHdNVGdnT0RRMExqQTVNeUF6TURRdU5URTNJRGcwTkM0MU1qWWdNekEwTGpVME9FdzROVE11TnpJMklETXdOUzR5TURkRE9EVTBMakU0TkNBek1EVXVNalFnT0RVMExqTXlNU0F6TURVdU56ZzNJRGcxTXk0NU5ESWdNekEyTGpBM01VdzRNek11T0RnMElETXlNUzR4TVRKRE9ETXpMalV3TmlBek1qRXVNemsySURnek15NDJORE1nTXpJeExqazBNeUE0TXpRdU1UQXhJRE15TVM0NU56Wk1PRFEwTGpBd055QXpNakl1TmpnMVF6ZzBOQzQwT1RFZ016SXlMamN5SURnME5DNDJNRFVnTXpJekxqTXhPU0E0TkRRdU1UYzNJRE15TXk0MU9FdzNPVGN1TnpVeUlETTFNUzQ1TlRSRE56azNMakl3T1NBek5USXVNamcySURjNU5pNDJPRGNnTXpVeExqWXpOQ0EzT1RjdU1UVTJJRE0xTVM0eU1EbE1PREU0TGpRd015QXpNekV1T1RJeVF6Z3hPQzQzTXpNZ016TXhMall5TWlBNE1UZ3VOVGMzSURNek1TNHhNak1nT0RFNExqRTBOU0F6TXpFdU1Ea3lURGd3T0M0M05EZ2dNek13TGpReVF6Z3dPQzR5T1RJZ016TXdMak00TnlBNE1EZ3VNVFUwSURNeU9TNDRORE1nT0RBNExqVXlPU0F6TWprdU5UVTRURGd5T0M0d05UUWdNekUwTGpjME5FTTRNamd1TkRNZ016RTBMalExT1NBNE1qZ3VNamt4SURNeE15NDVNVFVnT0RJM0xqZ3pOU0F6TVRNdU9EZ3lURGd4T0M0ek9Ea2dNekV6TGpJd05rTTRNVGN1T1RBMElETXhNeTR4TnpFZ09ERTNMamM1SURNeE1pNDFOeklnT0RFNExqSXhPQ0F6TVRJdU16RXhURGcyTkM0Mk5ETWdNamd6TGprek4xb2lJR1pwYkd3OUluZG9hWFJsSWlBdlBqeG5JSFJ5WVc1elptOXliVDBpYldGMGNtbDRLREF1T1RnM09ESTNJREF1TVRVMU5UVTNJQzB3TGpJMU5USTJNU0F3TGprMk5qZzNNaUF5TlRBZ056TTFLU0krUEhSbGVIUWdabTl1ZEMxbVlXMXBiSGs5SWtsdWRHVnlMQ0J6WVc1ekxYTmxjbWxtSWlCbWIyNTBMWGRsYVdkb2REMGlZbTlzWkNJZ1ptOXVkQzF6YVhwbFBTSTBNaUlnWm1sc2JEMGlJMFUxUlRkR09DSStUbVYzSUVGd2NDQk9ZVzFsUEM5MFpYaDBQangwWlhoMElHWnZiblF0Wm1GdGFXeDVQU0pKYm5SbGNpd2djMkZ1Y3kxelpYSnBaaUlnWm05dWRDMTNaV2xuYUhROUltNXZjbTFoYkNJZ2VUMGlOREFpSUdadmJuUXRjMmw2WlQwaU1qSWlJR1pwYkd3OUlpTTNSamd4T1RJaVBtNWxkeTFsYm5NdVpYUm9QQzkwWlhoMFBqd3ZaejQ4YVcxaFoyVWdkMmxrZEdnOUlqRTJOeUlnYUdWcFoyaDBQU0l4TmpjaUlIUnlZVzV6Wm05eWJUMGliV0YwY21sNEtEQXVPVGczT0RJM0lEQXVNVFUxTlRVM0lDMHdMakkxTlRJMk1TQXdMamsyTmpnM01pQTBORFF1TVRFM0lEVXlOQzR4TnlraUlHaHlaV1k5SW1SaGRHRTZhVzFoWjJVdmMzWm5LM2h0YkR0aVlYTmxOalFzVUVoT01scDVRakphV0VwNllWYzVkVkJUU1hoTWFrVnBTVWhvZEdKSE5YcFFVMHB2WkVoU2QwOXBPSFprTTJRelRHNWpla3h0T1hsYWVUaDVUVVJCZDB3elRqSmFlVWxuWlVjeGMySnVUVFpsUjNod1ltMXpPVWx0YURCa1NFRTJUSGs1TTJRelkzVmtlazExWWpOS2JreDZSVFZQVkd0MlpVZDRjR0p0YzJsSlNHYzVTV3BDZDJWRFNXZGxWREJwVFVoQ05FbHBRakpoVjFZelVXMDVORkJUU1hkSlJFRm5UVlJCZDAxRFFYaE5SRUYzU1dsQ2JHSnRSbWxpUjFWMFdXMUdhbUV5WkhsaU0xWjFXa1F3YVdKdFZqTkpSRUZuVFVOQmVFMUVRWGRKUkVWM1RVUkJhVWxJYUhSaVJIQjZZMGRHYWxwVU1HbGpTRXBzWXpKV2VXUnRWV2xRWjI4NFdubzBPR05IUmpCaFEwSnJVRk5LVGs1VVFYZE1SRVYzVVhwSmVVOVROREJNUkVWM1RFUkZkMHhFU1hsUFV6UXdURVJGZDB4RVZYZE5SMDEzVEVSSk0wMUROREpNUkVsNFQxTTBNRXhFVVRWTlEzY3dUMVJCYzA1RWEzZFpla2t6VFVNME1reEVRWE5PUkd0M1RGUkplRTlUTkRCTVJGRTFUVU13TUU5VVFrUlBWR3QzVEVSSmVVOVROREJNUkdNelRVTTBNa3hFUlhkTVJGVjNUVU4zZUUxSWIyZFVWR2Q0VGxOM05FMVVWbXBNVkZGM1RHcHJjMDVFUVhWUFV6QTBUME0wTWt4RVkzcE1ha1YwVFZSUmVFeHFXWE5QVkZWMVRsZE5kRTVVVVhWUFUzZDVUWGswZVV4VVJYaE5lVFI1VEVSTk1VeFVSVE5OZVRRd1RFUk5NVmw1TURKTlF6UjVURVJCZEUxVVJUUk1hbFYwVFZSRmRVOURNSGhPZWsxMVRrTXdlazVWVFhsT2VrMTFUbWwzTkU5RVozTk5ha2t4VEdwcmMwOUVWVEZNYW10elRWUm5NVXhFWjNoT1dFMTBUbnBOZEU5RVozVk9hVEExVGxNME1VeFVSVEJOVXpReVdYa3dlVTE1TkhsTVZGVXdUR3ByZEUxNlZYUk5WRVY2VEdwSmRFMTZWWFJOVkdONlRHcFNhazFETURKTlF6UjVURVJGZUV4cVozUk5WRVUwVEdwVmMwMTZWWFJOVkdONlRHcFNhazFxU1hWT1F6QXhUWGwzTVU1RE5ESk1WRVYzVFVNME0weEVhekZNYWxWMFRWUlJlRXhxV25wUFJHZDFUbWt3TTAxNWQzaE9SRVYxVG1rd05VNVROREZaZWxVd1RHcHJkRTFxVFhWTmFYZDRUVlJOZFUxcE1IcE9VM2Q0VG5wTmRVNURNSHBPVjAweVRVTTBlVXhFUVhOTlZFVTBUR3BWYzAxVVJYVlBRM2Q0VG5wTmRVNURkM3BPVjAweFRYbDNlVTFwTkRCTVJFVjNUVU0wTTB4RVZUQk1hbGx6VFZSUmVFeHFXWE5QVkZWMVRsZE5NRTFETkRWTVJGRjNUR3ByYzA1NlRYTlBSR2QxVG1sM05VNVROREZNUkVVd1RWTTBNbGw2U1hwTWFrbHpUbFJSZFU5VGQzcE9VM2Q0VFZSTmRVMXBkM3BPVTNkNFRucE5kVTVIVFhkTVJGbDNUR3BKZEUxVVJYVlBRM2Q0VFZSbmRVNVRNSHBPVTNkNFRucE5kVTVGVFRSUFJHZHpUbnBKTWt4cVVYTlBSRlV4VEdwcmMwNTZZekJNYWtWelQwUkZNVXhFWjNoT1dHOXBUSG8wT0V3eVl5dERhbmQyWXpOYWJsQm5QVDBpSUM4K1BHUmxabk0rUEdacGJIUmxjaUJwWkQwaVpHbHphMlYwZEdVdGMyaGhaRzkzSWlCNFBTSTNNQzQzTkRnNUlpQjVQU0l4T1RVdU56RXlJaUIzYVdSMGFEMGlPVFUxTGpjek15SWdhR1ZwWjJoMFBTSTRNekl1TlRVNElpQm1hV3gwWlhKVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR052Ykc5eUxXbHVkR1Z5Y0c5c1lYUnBiMjR0Wm1sc2RHVnljejBpYzFKSFFpSStQR1psUm14dmIyUWdabXh2YjJRdGIzQmhZMmwwZVQwaU1DSWdMejQ4Wm1WQ2JHVnVaQ0JwYmowaVUyOTFjbU5sUjNKaGNHaHBZeUlnTHo0OFptVkhZWFZ6YzJsaGJrSnNkWElnYzNSa1JHVjJhV0YwYVc5dVBTSTBNaUlnTHo0OEwyWnBiSFJsY2o0OGJHbHVaV0Z5UjNKaFpHbGxiblFnYVdROUltSmhZMnRuY205MWJtUWlJSGd4UFNJMU16SXVOU0lnZVRFOUlqQWlJSGd5UFNJMU16SXVOU0lnZVRJOUlqRXdOalVpSUdkeVlXUnBaVzUwVlc1cGRITTlJblZ6WlhKVGNHRmpaVTl1VlhObElqNDhjM1J2Y0NBdlBqeHpkRzl3SUc5bVpuTmxkRDBpTVNJZ2MzUnZjQzFqYjJ4dmNqMGlJekV6TVRNeE15SWdMejQ4TDJ4cGJtVmhja2R5WVdScFpXNTBQanh5WVdScFlXeEhjbUZrYVdWdWRDQnBaRDBpWW1GamEyZHliM1Z1WkMxeVlXUnBZV3dpSUdONFBTSXdJaUJqZVQwaU1DSWdjajBpTVNJZ1ozSmhaR2xsYm5SVmJtbDBjejBpZFhObGNsTndZV05sVDI1VmMyVWlJR2R5WVdScFpXNTBWSEpoYm5ObWIzSnRQU0owY21GdWMyeGhkR1VvTlRNeUxqVWdOVE15TGpVcElISnZkR0YwWlNnNE9TNDVOakVwSUhOallXeGxLRGN6TlNraVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTTJOVFF6TWpFaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTmpVME16SXhJaUJ6ZEc5d0xXOXdZV05wZEhrOUlqQWlJQzgrUEM5eVlXUnBZV3hIY21Ga2FXVnVkRDQ4YkdsdVpXRnlSM0poWkdsbGJuUWdhV1E5SW1ScGMydGxkSFJsTFdkeVlXUnBaVzUwSWlCNE1UMGlPVEkxTGpZeU5pSWdlVEU5SWpJMU5pNDRPVFlpSUhneVBTSXhNell1TnpjNUlpQjVNajBpT0RBd0xqSXdNeUlnWjNKaFpHbGxiblJWYm1sMGN6MGlkWE5sY2xOd1lXTmxUMjVWYzJVaVBqeHpkRzl3SUhOMGIzQXRZMjlzYjNJOUlpTTJOVFF6TWpFaUlDOCtQSE4wYjNBZ2IyWm1jMlYwUFNJeElpQnpkRzl3TFdOdmJHOXlQU0lqTWtNek1UTkdJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEd4cGJtVmhja2R5WVdScFpXNTBJR2xrUFNKdFlXbHVJajQ4YzNSdmNDQnpkRzl3TFdOdmJHOXlQU0lqTmpVME16SXhJaUF2UGp3dmJHbHVaV0Z5UjNKaFpHbGxiblErUEM5a1pXWnpQand2YzNablBnPT0iLCJhY2Nlc3NfcG9pbnRfYXV0b19hcHByb3ZhbCI6ZmFsc2UsInZlcmlmaWVkIjp0cnVlLCJhdHRyaWJ1dGVzIjogW3sidHJhaXRfdHlwZSI6ICJFTlMiLCAidmFsdWUiOiJuZXctZW5zLmV0aCJ9LHsidHJhaXRfdHlwZSI6ICJDb21taXQgSGFzaCIsICJ2YWx1ZSI6ImNlMWEzZmMxNDFlMjlmOGUxZDAwYTY1NGUxNTZjNDk4MmQ3NzExYmYifSx7InRyYWl0X3R5cGUiOiAiUmVwb3NpdG9yeSIsICJ2YWx1ZSI6Imh0dHBzOi8vZ2l0aHViLmNvbS9vdGhlci9yZXBvIn0seyJ0cmFpdF90eXBlIjogIlZlcnNpb24iLCAidmFsdWUiOiIxIn0seyJ0cmFpdF90eXBlIjogIkNvbG9yIiwgInZhbHVlIjoiIzY1NDMyMSJ9XX0=" ); } @@ -88,6 +89,7 @@ contract Test_FleekERC721_TokenURI is Test_FleekERC721_Base, Test_FleekERC721_To expectMetadataUpdate(tokenId, "externalURL", "https://new-url.com", deployer); CuT.setTokenExternalURL(tokenId, "https://new-url.com"); + transferENS("new-ens.eth", deployer); expectMetadataUpdate(tokenId, "ENS", "new-ens.eth", deployer); CuT.setTokenENS(tokenId, "new-ens.eth"); diff --git a/contracts/test/foundry/FleekERC721/Utils.sol b/contracts/test/foundry/FleekERC721/Utils.sol new file mode 100644 index 0000000..2ae0176 --- /dev/null +++ b/contracts/test/foundry/FleekERC721/Utils.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.17; + +import {FleekENS} from "contracts/util/FleekENS.sol"; + +library Utils { + /** + * @dev This function is copyed from `FleekENS.sol`. + * It changes the `internal` modifier to `public` allowing it + * to be used in tests applying memory values + */ + function namehash(string calldata name) public view returns (bytes32) { + return FleekENS.namehash(bytes(name), 0); + } +} diff --git a/contracts/test/hardhat/contracts/FleekERC721/ens.t.ts b/contracts/test/hardhat/contracts/FleekERC721/ens.t.ts new file mode 100644 index 0000000..bc60c8a --- /dev/null +++ b/contracts/test/hardhat/contracts/FleekERC721/ens.t.ts @@ -0,0 +1,56 @@ +import { expect } from 'chai'; +import { TestConstants, Fixtures, Errors, transferENSNode } from './helpers'; +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +const { MintParams } = TestConstants; + +describe('FleekERC721.ENS', () => { + let fixture: Awaited>; + + beforeEach(async () => { + fixture = await loadFixture(Fixtures.default); + }); + + it('should not allow mint if not ENS owner', async () => { + const { contract, owner } = fixture; + + await expect( + contract.mint( + owner.address, + MintParams.name, + MintParams.description, + MintParams.externalUrl, + 'app.eth', + MintParams.commitHash, + MintParams.gitRepository, + MintParams.logo, + MintParams.color, + MintParams.accessPointAutoApprovalSettings, + owner.address + ) + ).to.be.revertedWithCustomError(contract, Errors.MustBeENSOwner); + }); + + it('should not allow set ENS if not ENS owner', async () => { + const { contract, owner } = fixture; + + await transferENSNode('app.eth', owner); + + await contract.mint( + owner.address, + MintParams.name, + MintParams.description, + MintParams.externalUrl, + 'app.eth', + MintParams.commitHash, + MintParams.gitRepository, + MintParams.logo, + MintParams.color, + MintParams.accessPointAutoApprovalSettings, + owner.address + ); + + await expect( + contract.setTokenENS(0, 'subdomain.app.eth') + ).to.be.revertedWithCustomError(contract, Errors.MustBeENSOwner); + }); +}); diff --git a/contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts b/contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts index c7ef534..82b6b5d 100644 --- a/contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts +++ b/contracts/test/hardhat/contracts/FleekERC721/helpers/errors.ts @@ -15,4 +15,5 @@ export const Errors = Object.freeze({ PausableIsSetTo: 'PausableIsSetTo', ThereIsNoTokenMinted: 'ThereIsNoTokenMinted', RequiredPayment: 'RequiredPayment', + MustBeENSOwner: 'MustBeENSOwner', }); diff --git a/contracts/test/hardhat/contracts/FleekERC721/helpers/fixture.ts b/contracts/test/hardhat/contracts/FleekERC721/helpers/fixture.ts index f16d5e0..7e82e64 100644 --- a/contracts/test/hardhat/contracts/FleekERC721/helpers/fixture.ts +++ b/contracts/test/hardhat/contracts/FleekERC721/helpers/fixture.ts @@ -1,11 +1,14 @@ import { ethers, upgrades } from 'hardhat'; import { TestConstants } from './constants'; +import { transferENSNode } from './utils'; export abstract class Fixtures { static async default() { // Contracts are deployed using the first signer/account by default const [owner, otherAccount] = await ethers.getSigners(); + await transferENSNode(TestConstants.MintParams.ens, owner); + const libraries = { FleekSVG: (await (await ethers.getContractFactory('FleekSVG')).deploy()) .address, diff --git a/contracts/test/hardhat/contracts/FleekERC721/helpers/utils.ts b/contracts/test/hardhat/contracts/FleekERC721/helpers/utils.ts index c040691..ceed2e9 100644 --- a/contracts/test/hardhat/contracts/FleekERC721/helpers/utils.ts +++ b/contracts/test/hardhat/contracts/FleekERC721/helpers/utils.ts @@ -1,3 +1,10 @@ +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import { ethers, upgrades } from 'hardhat'; +import { TestConstants } from './constants'; + +// eslint-disable-next-line @typescript-eslint/no-var-requires +const namehash = require('@ensdomains/eth-ens-namehash'); + export const parseTokenURI = (tokenURI: string) => { const tokenURIDecoded = Buffer.from( tokenURI.replace('data:application/json;base64,', ''), @@ -6,3 +13,25 @@ export const parseTokenURI = (tokenURI: string) => { return JSON.parse(tokenURIDecoded); }; + +export const getENSNode = (name: string) => { + return namehash.hash(namehash.normalize(name)); +}; + +export const transferENSNode = async (name: string, to: SignerWithAddress) => { + const ens = await ethers.getContractAt( + 'ENS', + '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e' + ); + + const ensNode = getENSNode(name); + + const ensOwner = await ethers.getImpersonatedSigner(await ens.owner(ensNode)); + + await to.sendTransaction({ + to: ensOwner.address, + value: ethers.utils.parseEther('1000'), + }); + + await ens.connect(ensOwner).setOwner(ensNode, to.address); +}; diff --git a/contracts/test/hardhat/contracts/FleekERC721/update-properties.t.ts b/contracts/test/hardhat/contracts/FleekERC721/update-properties.t.ts index 3e21895..57db432 100644 --- a/contracts/test/hardhat/contracts/FleekERC721/update-properties.t.ts +++ b/contracts/test/hardhat/contracts/FleekERC721/update-properties.t.ts @@ -1,6 +1,6 @@ import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; import { expect } from 'chai'; -import { TestConstants, Fixtures, Events } from './helpers'; +import { TestConstants, Fixtures, Events, transferENSNode } from './helpers'; const { Logos: { 1: Logo1 }, @@ -25,9 +25,11 @@ describe('FleekERC721.UpdateProperties', () => { it('should emit event for ens change', async () => { const { contract, tokenId, owner } = fixture; - await expect(contract.setTokenENS(tokenId, 'app.eth')) + await transferENSNode('subdomain.app.eth', owner); + + await expect(contract.setTokenENS(tokenId, 'subdomain.app.eth')) .to.emit(contract, Events.MetadataUpdate.string) - .withArgs(tokenId, 'ENS', 'app.eth', owner.address); + .withArgs(tokenId, 'ENS', 'subdomain.app.eth', owner.address); }); it('should emit event for name change', async () => { diff --git a/contracts/yarn.lock b/contracts/yarn.lock index f8b90dc..f201b03 100644 --- a/contracts/yarn.lock +++ b/contracts/yarn.lock @@ -14,6 +14,33 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@ensdomains/buffer@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@ensdomains/buffer/-/buffer-0.1.1.tgz#6c275ba7e457e935405b67876f1f0d980c8baa63" + integrity sha512-92SfSiNS8XorgU7OUBHo/i1ZU7JV7iz/6bKuLPNVsMxV79/eI7fJR6jfJJc40zAHjs3ha+Xo965Idomlq3rqnw== + +"@ensdomains/ens-contracts@^0.0.20": + version "0.0.20" + resolved "https://registry.yarnpkg.com/@ensdomains/ens-contracts/-/ens-contracts-0.0.20.tgz#346eac70d666a7864142287ce1759b0f44bd8a5e" + integrity sha512-lAHQBVj2WtgbchcrE8ZuFI6DFq+O33wkLAGqsO2gcnn0EUJb65OJIdTqUfvfULKGJjkB2pyHfS/RgMSIW6h1Pw== + dependencies: + "@ensdomains/buffer" "^0.1.1" + "@ensdomains/solsha1" "0.0.3" + "@openzeppelin/contracts" "^4.1.0" + dns-packet "^5.3.0" + +"@ensdomains/eth-ens-namehash@^2.0.15": + version "2.0.15" + resolved "https://registry.yarnpkg.com/@ensdomains/eth-ens-namehash/-/eth-ens-namehash-2.0.15.tgz#5e5f2f24ba802aff8bc19edd822c9a11200cdf4a" + integrity sha512-JRDFP6+Hczb1E0/HhIg0PONgBYasfGfDheujmfxaZaAv/NAH4jE6Kf48WbqfRZdxt4IZI3jl3Ri7sZ1nP09lgw== + +"@ensdomains/solsha1@0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@ensdomains/solsha1/-/solsha1-0.0.3.tgz#fd479da9d40aadb59ff4fb4ec50632e7d2275a83" + integrity sha512-uhuG5LzRt/UJC0Ux83cE2rCKwSleRePoYdQVcqPN1wyf3/ekMzT/KZUF9+v7/AG5w9jlMLCQkUM50vfjr0Yu9Q== + dependencies: + hash-test-vectors "^1.3.2" + "@ethereumjs/common@2.5.0": version "2.5.0" resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.5.0.tgz#ec61551b31bef7a69d1dc634d8932468866a4268" @@ -398,6 +425,11 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + "@metamask/eth-sig-util@^4.0.0": version "4.0.1" resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz#3ad61f6ea9ad73ba5b19db780d40d9aae5157088" @@ -700,6 +732,11 @@ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.1.tgz#363f7dd08f25f8f77e16d374350c3d6b43340a7a" integrity sha512-1wTv+20lNiC0R07jyIAbHU7TNHKRwGiTGRfiNnA8jOWjKT98g5OgLpYWOi40Vgpk8SPLA9EvfJAbAeIyVn+7Bw== +"@openzeppelin/contracts@^4.1.0": + version "4.8.2" + resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.2.tgz#d815ade0027b50beb9bcca67143c6bcc3e3923d6" + integrity sha512-kEUOgPQszC0fSYWpbh2kT94ltOJwj1qfT2DWo+zVttmGmf97JZ99LspePNaeeaLhCImaHVeBbjaQFZQn7+Zc5g== + "@openzeppelin/contracts@^4.7.3": version "4.8.1" resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.1.tgz#709cfc4bbb3ca9f4460d60101f15dac6b7a2d5e4" @@ -2155,6 +2192,13 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +dns-packet@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" + integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== + dependencies: + "@leichtgewicht/ip-codec" "^2.0.1" + dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" @@ -3302,6 +3346,11 @@ hash-base@^3.0.0: readable-stream "^3.6.0" safe-buffer "^5.2.0" +hash-test-vectors@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/hash-test-vectors/-/hash-test-vectors-1.3.2.tgz#f050fde1aff46ec28dcf4f70e4e3238cd5000f4c" + integrity sha512-PKd/fitmsrlWGh3OpKbgNLE04ZQZsvs1ZkuLoQpeIKuwx+6CYVNdW6LaPIS1QAdZvV40+skk0w4YomKnViUnvQ== + hash.js@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846"