chore: prepare the contracts to be upgradable using openzeppelin proxy plugin (#76)

* feat: add proxy upgradable base setting

* refactor: upgrade contracts to fit upgradable pattern

* fix: hardhat test default fixture

* test: trying to fix foundry tests

* fix: remove wrong modifier from FleekAccessControl initializer

* refactor: change __FleekAccessControl_init function from public to internal

* refactor: add __FleekAccessControl_init modifier

* feat: proxy store script

* chore: add .openzeppelin development files in gitignore

* refactor: update local deploy script to use proxy

* refactor: mumbai deployment with proxy and fix interaction scripts

* test: fix proxy storing values

* refactor: proxy storage deploy order

* test: move proxy test to deploy folder

* refactor: deployment scripts

* docs: fix local deploy command

* refactor: add more logs in deploy scripts

* feat: write deployment files script

* refactor: use file scripts in proxy-deploy

* refactor: deployment files for mumbai
This commit is contained in:
Felipe Mendes 2023-01-31 12:09:12 -03:00 committed by GitHub
parent 61aeaaae66
commit 91aeb47aef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 2174 additions and 630 deletions

5
.gitignore vendored
View File

@ -4,7 +4,7 @@ node_modules
# hardhat
cache
artifacts
deployments/localhost
deployments/hardhat
# NPM
package-lock.json
@ -13,6 +13,9 @@ package-lock.json
out
forge-cache
# OpenZeppelin
.openzeppelin/unknown-*.json
# Subgraph
*.wasm
subgraph/build

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@
> 🚧 IMPORTANT 🚧 - This initiative is under development, so this repo should be treated as a WIP. The goals and the roadmap might change as the project is shaped.
## ⚡ Overview
This is the landing point for Fleek's initiative to implement infrastructure as Solidity contracts.
@ -154,7 +153,7 @@ $ yarn node:hardhat
To deploy the contract on the HardHat network, execute:
```
$ yarn deploy:local
$ yarn deploy:hardhat
```
If the execution is successful, you will see the contract address on your screen.

View File

@ -3,8 +3,9 @@
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
contract FleekAccessControl {
contract FleekAccessControl is Initializable {
using Counters for Counters.Counter;
enum Roles {
@ -33,7 +34,7 @@ contract FleekAccessControl {
/**
* @dev Initializes the contract by granting the `Owner` role to the deployer.
*/
constructor() {
function __FleekAccessControl_init() internal onlyInitializing {
_grantCollectionRole(Roles.Owner, msg.sender);
}

View File

@ -2,13 +2,15 @@
pragma solidity ^0.8.7;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "./FleekAccessControl.sol";
import "./util/FleekStrings.sol";
contract FleekERC721 is ERC721, FleekAccessControl {
contract FleekERC721 is Initializable, ERC721Upgradeable, FleekAccessControl {
using Strings for uint256;
using Counters for Counters.Counter;
using FleekStrings for FleekERC721.App;
using FleekStrings for FleekERC721.AccessPoint;
@ -84,7 +86,10 @@ contract FleekERC721 is ERC721, FleekAccessControl {
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/
constructor(string memory _name, string memory _symbol) ERC721(_name, _symbol) {}
function initialize(string memory _name, string memory _symbol) public initializer {
__ERC721_init(_name, _symbol);
__FleekAccessControl_init();
}
/**
* @dev Checks if the AccessPoint exists.
@ -152,7 +157,7 @@ contract FleekERC721 is ERC721, FleekAccessControl {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721) returns (bool) {
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC721Upgradeable) returns (bool) {
return super.supportsInterface(interfaceId);
}

View File

@ -1,29 +0,0 @@
const contractName = 'FleekERC721';
const args = [
'FleekNFAs', // Collection name
'FLKNFA', // Collection symbol
];
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments;
const namedAccounts = await getNamedAccounts();
const { localDeployer: deployer } = namedAccounts;
const deployResult = await deploy(contractName, {
from: deployer,
args,
});
if (deployResult.newlyDeployed) {
log(
`Contract ${contractName} deployed at ${deployResult.address} using ${deployResult.receipt.gasUsed} gas by account ${deployer}`
);
} else {
log(
`Using pre-existing contract ${contractName} at ${deployResult.address}`
);
}
};
//You can put an array of tags below. Tags can be anything and say when a this script should be run. So you can write different scripts for local, prod or other deploys
//For example when you run 'npx hardhat --network hardhat deploy --tags local' hardhat will run all deploy scripts that have the tag local, could be multiple dif scripts
module.exports.tags = ['local'];

View File

@ -1,35 +0,0 @@
const contractName = 'FleekERC721';
const args = [
'FleekNFAs', // Collection name
'FLKNFA', // Collection symbol
];
module.exports = async ({ getNamedAccounts, deployments }) => {
const { deploy, log } = deployments;
const namedAccounts = await getNamedAccounts();
const { privateKey } = namedAccounts;
if (!privateKey) {
log('Please set "PRIVATE_KEY" environment variable to deploy to Mumbai');
throw new Error('Missing private key');
}
const deployResult = await deploy(contractName, {
from: privateKey,
args,
});
if (deployResult.newlyDeployed) {
log(
`Contract ${contractName} deployed at ${deployResult.address} using ${deployResult.receipt.gasUsed} gas`
);
} else {
log(
`Using pre-existing contract ${contractName} at ${deployResult.address}`
);
}
};
//You can put an array of tags below. Tags can be anything and say when a this script should be run. So you can write different scripts for local, prod or other deploys
//For example when you run 'npx hardhat --network hardhat deploy --tags local' hardhat will run all deploy scripts that have the tag local, could be multiple dif scripts
module.exports.tags = ['mumbai'];

View File

@ -1 +0,0 @@
80001

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,12 @@
{
"FleekERC721": [
{
"address": "0x21d7fBe220958A0F0f7cAE58780fe812EbcB3cd8",
"timestamp": "1/16/2023, 8:51:51 AM"
},
{
"address": "0x84Dc9a43B3472415a406e1a14d6b94a5c289eF7F",
"timestamp": "1/16/2023, 8:49:22 AM"
}
]
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -2,10 +2,10 @@ import '@nomiclabs/hardhat-etherscan';
import '@nomiclabs/hardhat-ethers';
import '@nomiclabs/hardhat-web3';
import '@nomicfoundation/hardhat-chai-matchers';
import 'hardhat-deploy';
import 'solidity-coverage';
import 'hardhat-gas-reporter';
import 'hardhat-contract-sizer';
import '@openzeppelin/hardhat-upgrades';
import * as dotenv from 'dotenv';
import { HardhatUserConfig } from 'hardhat/types';
@ -24,13 +24,9 @@ const config: HardhatUserConfig = {
hardhat: {
chainId: 31337,
},
localhost: {
chainId: 31337,
},
mumbai: {
url: API_URL,
accounts: PRIVATE_KEY ? [PRIVATE_KEY] : [],
saveDeployments: true,
chainId: 80001,
},
},
@ -45,14 +41,6 @@ const config: HardhatUserConfig = {
runOnCompile: false,
only: ['NftMarketplace'],
},
namedAccounts: {
localDeployer: {
default: 0,
},
privateKey: {
default: PRIVATE_KEY ? `privatekey://${PRIVATE_KEY}` : null,
},
},
solidity: {
version: '0.8.12',
settings: {

View File

@ -8,9 +8,9 @@
"test:foundry": "forge test --via-ir",
"test:hardhat": "hardhat test",
"format": "prettier --write \"./**/*.{js,json,sol,ts}\"",
"node:hardhat": "hardhat node --tags local",
"deploy:local": "hardhat deploy --tags local --network localhost",
"deploy:mumbai": "hardhat deploy --tags mumbai --network mumbai",
"node:hardhat": "hardhat node",
"deploy:hardhat": "hardhat run scripts/deploy.js --network hardhat",
"deploy:mumbai": "hardhat run scripts/deploy.js --network mumbai",
"compile": "hardhat compile",
"postinstall": "husky install",
"prepack": "pinst --disable",
@ -35,13 +35,14 @@
"@nomiclabs/hardhat-etherscan": "^3.1.0",
"@nomiclabs/hardhat-web3": "^2.0.0",
"@openzeppelin/contracts": "^4.7.3",
"@openzeppelin/contracts-upgradeable": "^4.8.0",
"@openzeppelin/hardhat-upgrades": "^1.22.0",
"@types/mocha": "^10.0.1",
"chai": "^4.3.6",
"dotenv": "^16.0.2",
"ethers": "^5.7.2",
"hardhat": "^2.11.2",
"hardhat-contract-sizer": "^2.6.1",
"hardhat-deploy": "^0.11.15",
"hardhat-gas-reporter": "^1.0.9",
"husky": "^8.0.2",
"lint-staged": "^13.0.4",

53
scripts/deploy.js Normal file
View File

@ -0,0 +1,53 @@
const { deployStore } = require('./utils/deploy-store');
const { getProxyAddress, proxyStore } = require('./utils/proxy-store');
const CONTRACT_NAME = 'FleekERC721';
const NETWORK = hre.network.name;
const ARGUMENTS = [
'FleekNFAs', // Collection name
'FLKNFA', // Collection symbol
];
const deploy = async () => {
const Contract = await ethers.getContractFactory(CONTRACT_NAME);
const proxyAddress = await getProxyAddress(CONTRACT_NAME, NETWORK);
let deployResult;
try {
if (!proxyAddress) throw new Error('No proxy address found');
console.log(`Trying to upgrade proxy contract at: "${proxyAddress}"`);
deployResult = await upgrades.upgradeProxy(proxyAddress, Contract);
console.log(
`Contract ${CONTRACT_NAME} upgraded at "${deployResult.address}" by account "${deployResult.signer.address}"`
);
await deployStore(NETWORK, CONTRACT_NAME, deployResult);
} catch (e) {
if (
e.message === 'No proxy address found' ||
e.message.includes("doesn't look like an ERC 1967 proxy")
) {
console.log(`Failed to upgrade proxy contract: "${e.message?.trim()}"`);
console.log('Creating new proxy contract...');
deployResult = await upgrades.deployProxy(Contract, ARGUMENTS);
await deployResult.deployed();
await proxyStore(CONTRACT_NAME, deployResult.address, hre.network.name);
console.log(
`Contract ${CONTRACT_NAME} deployed at "${deployResult.address}" by account "${deployResult.signer.address}"`
);
} else {
throw e;
}
try {
await deployStore(NETWORK, CONTRACT_NAME, deployResult);
} catch (e) {
console.error('Could not write deploy files', e);
}
}
};
console.log(':: Starting Deployment ::');
console.log('Network:', NETWORK);
console.log('Contract:', CONTRACT_NAME);
deploy();

View File

@ -6,16 +6,14 @@ const params = [
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049', // to
'Fleek App', // name
'Description', // description
'https://fleek.network/fleek-network-logo-minimal.png', // image
'https://fleek.co/', // external url
'fleek.eth', // ens
'6ea6ad16c46ae85faced7e50555ff7368422f57', // commit hash
'https://github.com/org/repo', // repo
'fleek', // author
];
(async () => {
const contract = getContract('FleekERC721');
const contract = await getContract('FleekERC721');
const transaction = await contract.mint(...params);

View File

@ -2,7 +2,7 @@
const { getContract } = require('./util');
// TODO: make this arguments
const tokenId = 1;
const tokenId = 0;
(async () => {
const contract = await getContract('FleekERC721');

View File

@ -1,7 +1,14 @@
module.exports.getContract = async function (contractName) {
const {
address,
} = require(`../deployments/${hre.network.name}/${contractName}.json`);
const proxyDeployments =
require(`../deployments/${hre.network.name}/proxy.json`)[contractName];
return hre.ethers.getContractAt(contractName, address);
if (!proxyDeployments || !proxyDeployments.length) {
throw new Error(
`No proxy deployments found for "${contractName}" under "${hre.network.name}"`
);
}
const latestDeployment = proxyDeployments[0];
return hre.ethers.getContractAt(contractName, latestDeployment.address);
};

View File

@ -0,0 +1,49 @@
const { writeFile } = require('./file');
const path = require('path');
const getDeployFilePath = (network, contractName) => {
return path.resolve(
__dirname,
`../../deployments/${network}/${contractName}.json`
);
};
module.exports.deployStore = async (network, contractName, contract) => {
const filePath = getDeployFilePath(network, contractName);
const buildArtifact = await hre.artifacts.readArtifact(contractName);
const {
id: buildId,
input: solcInput,
output: solcOutput,
} = await hre.artifacts.getBuildInfo(
`${buildArtifact.sourceName}:${buildArtifact.contractName}`
);
const contractOutput =
solcOutput.contracts[buildArtifact.sourceName][contractName];
const data = {
timestamp: new Date().toLocaleString('en-US'),
address: contract.address,
transactionHash: contract.deployTransaction.hash,
args: contract.deployTransaction.args,
gasPrice: contract.deployTransaction.gasPrice.toNumber(),
abi: contractOutput.abi,
bytecode: buildArtifact.bytecode,
metadata: contractOutput.metadata,
storageLayout: contractOutput.storageLayout,
};
try {
const solcInputsFilePath =
filePath.split('/').slice(0, -1).join('/') +
`/solcInputs/${buildId}.json`;
console.log('Writing deploy files', filePath);
await writeFile(filePath, JSON.stringify(data, null, 2));
await writeFile(solcInputsFilePath, JSON.stringify(solcInput, null, 2));
} catch (err) {
throw `Could not write file: ${err}`;
}
};

20
scripts/utils/file.js Normal file
View File

@ -0,0 +1,20 @@
const { existsSync, promises: fs } = require('fs');
const createFolder = async (filePath) => {
const folderPath = filePath.split('/').slice(0, -1).join('/');
if (!existsSync(folderPath)) {
try {
await fs.mkdir(folderPath, {
recursive: true,
});
} catch (err) {
throw `Could not create network folder: ${err}`;
}
}
};
module.exports.writeFile = async (filePath, data) => {
await createFolder(filePath);
return fs.writeFile(filePath, data);
};

View File

@ -0,0 +1,45 @@
const { existsSync } = require('fs');
const path = require('path');
const { writeFile } = require('./file');
const getProxyFilePath = (network) => {
return path.resolve(__dirname, `../../deployments/${network}/proxy.json`);
};
module.exports.proxyStore = async (contract, proxyAddress, network) => {
const filePath = getProxyFilePath(network);
const file = existsSync(filePath) ? require(filePath) : {};
const newRecord = {
address: proxyAddress,
timestamp: new Date().toLocaleString('en-US'),
};
if (file[contract]) {
file[contract].unshift(newRecord);
} else {
file[contract] = [newRecord];
}
try {
console.log('Writing proxy file', filePath);
await writeFile(filePath, JSON.stringify(file, null, 2));
} catch (err) {
throw `Could not write file: ${err}`;
}
};
module.exports.getProxyFilePath = getProxyFilePath;
module.exports.getProxyAddress = (contract, network) => {
const filePath = getProxyFilePath(network);
return new Promise((resolve) => {
try {
const proxyList = require(filePath)[contract];
const lastItem = proxyList[0];
resolve(lastItem.address);
} catch (err) {
resolve();
}
});
};

View File

@ -1,6 +1,6 @@
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
import { expect } from 'chai';
import { ethers } from 'hardhat';
import { ethers, upgrades } from 'hardhat';
describe('FleekERC721', () => {
const ROLES = Object.freeze({
@ -28,10 +28,10 @@ describe('FleekERC721', () => {
const [owner, otherAccount] = await ethers.getSigners();
const Contract = await ethers.getContractFactory('FleekERC721');
const contract = await Contract.deploy(
const contract = await upgrades.deployProxy(Contract, [
COLLECTION_PARAMS.name,
COLLECTION_PARAMS.symbol
);
COLLECTION_PARAMS.symbol,
]);
return { owner, otherAccount, contract };
};

View File

@ -0,0 +1,36 @@
import { expect } from 'chai';
import { proxyStore, getProxyFilePath } from '../../scripts/utils/proxy-store';
import fs from 'fs/promises';
describe('Proxy Store', () => {
const network = 'test';
const contractName = 'FleekERC721';
const proxyAddress = '0x91A425C1CA320A99a09BE1bee114Fce5d30153d9';
afterEach(async () => {
await fs.rm(getProxyFilePath(network));
});
it('should store the data', async () => {
await proxyStore(contractName, proxyAddress, network);
const file = require(getProxyFilePath(network));
expect(file[contractName]).to.eql([
{ address: proxyAddress, timestamp: new Date().toLocaleString('en-US') },
]);
});
it('should update the data', async () => {
const newProxyAddress = '0xB8594DC01580884AD69FE5d78EDEA5e66BeB5fFA';
await proxyStore(contractName, proxyAddress, network);
await proxyStore(contractName, newProxyAddress, network);
const file = require(getProxyFilePath(network));
expect(file[contractName]).to.eql([
{
address: newProxyAddress,
timestamp: new Date().toLocaleString('en-US'),
},
{ address: proxyAddress, timestamp: new Date().toLocaleString('en-US') },
]);
});
});

20
test/deploy/proxy.ts Normal file
View File

@ -0,0 +1,20 @@
import { expect } from 'chai';
import { ethers, upgrades } from 'hardhat';
describe('Proxy', function () {
it('FleekERC721', async () => {
const Contract = await ethers.getContractFactory('FleekERC721');
const ContractV2 = await ethers.getContractFactory('FleekERC721');
const instance = await upgrades.deployProxy(Contract, [
'Collection Name',
'SYMBOL',
]);
const upgraded = await upgrades.upgradeProxy(instance.address, ContractV2);
const name = await upgraded.name();
const symbol = await upgraded.symbol();
expect(name).to.equal('Collection Name');
expect(symbol).to.equal('SYMBOL');
});
});

View File

@ -11,7 +11,8 @@ contract FleekTest is Test {
string constant FLEEK_AP_URL = "https://fleek_cloned.xyz";
function setUp() public {
fleekContract = new FleekERC721("Test Contract", "FLKAPS");
fleekContract = new FleekERC721();
fleekContract.initialize("Test Contract", "FLKAPS");
}
function testName() public {

171
yarn.lock
View File

@ -1187,11 +1187,39 @@
dependencies:
"@types/bignumber.js" "^5.0.0"
"@openzeppelin/contracts-upgradeable@^4.8.0":
version "4.8.0"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.0.tgz#26688982f46969018e3ed3199e72a07c8d114275"
integrity sha512-5GeFgqMiDlqGT8EdORadp1ntGF0qzWZLmEY7Wbp/yVhN7/B3NNzCxujuI77ktlyG81N3CUZP8cZe3ZAQ/cW10w==
"@openzeppelin/contracts@^4.7.3":
version "4.8.0"
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.8.0.tgz#6854c37df205dd2c056bdfa1b853f5d732109109"
integrity sha512-AGuwhRRL+NaKx73WKRNzeCxOCOCxpaqF+kp8TJ89QzAipSwZy/NoflkWaL9bywXFRhIzXt8j38sfF7KBKCPWLw==
"@openzeppelin/hardhat-upgrades@^1.22.0":
version "1.22.0"
resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.22.0.tgz#2a432c72a428a9f277201646bc1a248021538f06"
integrity sha512-1qyZnDaxl0C8tne7ykNRa/fxw3FrNCY2M3fGuCiQW5DDkJoXhLgm3JVsXwl6X7q9mQSrik4vgBbI3ErmxmZTYg==
dependencies:
"@openzeppelin/upgrades-core" "^1.20.0"
chalk "^4.1.0"
debug "^4.1.1"
proper-lockfile "^4.1.1"
"@openzeppelin/upgrades-core@^1.20.0":
version "1.20.6"
resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.20.6.tgz#74f43d600151b8fda6e2d375f46ae0da55922620"
integrity sha512-KWdtlahm+iunlAlzLsdpBueanwEx0LLPfAkDL1p0C4SPjMiUqHHFlyGtmmWwdiqDpJ//605vfwkd5RqfnFrHSg==
dependencies:
cbor "^8.0.0"
chalk "^4.1.0"
compare-versions "^5.0.0"
debug "^4.1.1"
ethereumjs-util "^7.0.3"
proper-lockfile "^4.1.1"
solidity-ast "^0.4.15"
"@peculiar/asn1-schema@^2.1.6", "@peculiar/asn1-schema@^2.3.0":
version "2.3.3"
resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.3.tgz#21418e1f3819e0b353ceff0c2dad8ccb61acd777"
@ -1511,7 +1539,7 @@
dependencies:
"@types/node" "*"
"@types/qs@^6.2.31", "@types/qs@^6.9.7":
"@types/qs@^6.2.31":
version "6.9.7"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
@ -1881,13 +1909,6 @@ aws4@^1.8.0:
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59"
integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==
axios@^0.21.1:
version "0.21.4"
resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575"
integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==
dependencies:
follow-redirects "^1.14.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@ -2231,7 +2252,7 @@ catering@^2.1.0, catering@^2.1.1:
resolved "https://registry.yarnpkg.com/catering/-/catering-2.1.1.tgz#66acba06ed5ee28d5286133982a927de9a04b510"
integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==
cbor@^8.1.0:
cbor@^8.0.0, cbor@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/cbor/-/cbor-8.1.0.tgz#cfc56437e770b73417a2ecbfc9caf6b771af60d5"
integrity sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==
@ -2267,7 +2288,7 @@ chalk@^2.0.0, chalk@^2.4.2:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2:
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -2556,6 +2577,11 @@ common-tags@1.8.2:
resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6"
integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==
compare-versions@^5.0.0:
version "5.0.3"
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-5.0.3.tgz#a9b34fea217472650ef4a2651d905f42c28ebfd7"
integrity sha512-4UZlZP8Z99MGEY+Ovg/uJxJuvoXuN4M6B3hKaiackiHrgzQFEe3diJi1mf1PNHbFujM7FvLrK2bpgIaImbtZ1A==
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@ -2783,7 +2809,7 @@ debug@3.2.6:
dependencies:
ms "^2.1.1"
debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
debug@4, debug@4.3.4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@ -3006,11 +3032,6 @@ emoji-regex@^9.2.2:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
encode-utf8@^1.0.2:
version "1.0.3"
resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda"
integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==
encodeurl@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
@ -3023,7 +3044,7 @@ end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
enquirer@^2.3.0, enquirer@^2.3.6:
enquirer@^2.3.0:
version "2.3.6"
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
@ -3284,7 +3305,7 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1:
ethjs-util "0.1.6"
rlp "^2.2.3"
ethereumjs-util@^7.0.10, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5:
ethereumjs-util@^7.0.10, ethereumjs-util@^7.0.3, ethereumjs-util@^7.1.0, ethereumjs-util@^7.1.1, ethereumjs-util@^7.1.2, ethereumjs-util@^7.1.4, ethereumjs-util@^7.1.5:
version "7.1.5"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181"
integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==
@ -3310,7 +3331,7 @@ ethers@^4.0.40:
uuid "2.0.1"
xmlhttprequest "1.8.0"
ethers@^5.5.3, ethers@^5.7.2:
ethers@^5.7.2:
version "5.7.2"
resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e"
integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==
@ -3567,14 +3588,7 @@ flat@^5.0.2:
resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
fmix@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c"
integrity sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==
dependencies:
imul "^1.0.0"
follow-redirects@^1.12.1, follow-redirects@^1.14.0:
follow-redirects@^1.12.1:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
@ -3619,15 +3633,6 @@ form-data@^3.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
@ -3676,15 +3681,6 @@ fs-extra@^0.30.0:
path-is-absolute "^1.0.0"
rimraf "^2.2.8"
fs-extra@^10.0.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
dependencies:
graceful-fs "^4.2.0"
jsonfile "^6.0.1"
universalify "^2.0.0"
fs-extra@^4.0.2:
version "4.0.3"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94"
@ -3975,7 +3971,7 @@ got@^11.8.5:
p-cancelable "^2.0.0"
responselike "^2.0.0"
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0:
graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.10"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
@ -4011,11 +4007,6 @@ graphql-ws@5.11.2:
resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-5.11.2.tgz#d5e0acae8b4d4a4cf7be410a24135cfcefd7ddc0"
integrity sha512-4EiZ3/UXYcjm+xFGP544/yW1+DVI8ZpKASFbzrV5EDTFWJp0ZvLl4Dy2fSZAzz9imKp5pZMIcjB0x/H69Pv/6w==
graphql@^16.6.0:
version "16.6.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.6.0.tgz#c2dcffa4649db149f6282af726c8c83f1c7c5fdb"
integrity sha512-KPIBPDlW7NxrbT/eh4qPXz5FiFdL5UbaA0XUNz2Rp3Z3hqBSkbj0GVjwFDztsWVauZUWsbKHgMg++sk8UX0bkw==
growl@1.10.5:
version "1.10.5"
resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e"
@ -4054,25 +4045,6 @@ hardhat-contract-sizer@^2.6.1:
chalk "^4.0.0"
cli-table3 "^0.6.0"
hardhat-deploy@^0.11.15:
version "0.11.22"
resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.11.22.tgz#9799c0266a0fc40c84690de54760f1b4dae5e487"
integrity sha512-ZhHVNB7Jo2l8Is+KIAk9F8Q3d7pptyiX+nsNbIFXztCz81kaP+6kxNODRBqRCy7SOD3It4+iKCL6tWsPAA/jVQ==
dependencies:
"@types/qs" "^6.9.7"
axios "^0.21.1"
chalk "^4.1.2"
chokidar "^3.5.2"
debug "^4.3.2"
enquirer "^2.3.6"
ethers "^5.5.3"
form-data "^4.0.0"
fs-extra "^10.0.0"
match-all "^1.2.6"
murmur-128 "^0.2.1"
qs "^6.9.4"
zksync-web3 "^0.8.1"
hardhat-gas-reporter@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz#9a2afb354bc3b6346aab55b1c02ca556d0e16450"
@ -4368,11 +4340,6 @@ import-from@4.0.0:
resolved "https://registry.yarnpkg.com/import-from/-/import-from-4.0.0.tgz#2710b8d66817d232e16f4166e319248d3d5492e2"
integrity sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==
imul@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9"
integrity sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==
indent-string@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
@ -4784,15 +4751,6 @@ jsonfile@^4.0.0:
optionalDependencies:
graceful-fs "^4.1.6"
jsonfile@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
dependencies:
universalify "^2.0.0"
optionalDependencies:
graceful-fs "^4.1.6"
jsonify@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.1.tgz#2aa3111dae3d34a0f151c63f3a45d995d9420978"
@ -5072,11 +5030,6 @@ markdown-table@^1.1.3:
resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60"
integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==
match-all@^1.2.6:
version "1.2.6"
resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d"
integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==
mcl-wasm@^0.7.1:
version "0.7.9"
resolved "https://registry.yarnpkg.com/mcl-wasm/-/mcl-wasm-0.7.9.tgz#c1588ce90042a8700c3b60e40efb339fc07ab87f"
@ -5443,15 +5396,6 @@ multihashes@^0.4.15, multihashes@~0.4.15:
multibase "^0.7.0"
varint "^5.0.0"
murmur-128@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d"
integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==
dependencies:
encode-utf8 "^1.0.2"
fmix "^0.1.0"
imul "^1.0.0"
mute-stream@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
@ -5959,6 +5903,15 @@ promise@^8.0.0:
dependencies:
asap "~2.0.6"
proper-lockfile@^4.1.1:
version "4.1.2"
resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f"
integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==
dependencies:
graceful-fs "^4.2.4"
retry "^0.12.0"
signal-exit "^3.0.2"
proxy-addr@~2.0.7:
version "2.0.7"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
@ -6014,7 +5967,7 @@ pvutils@^1.1.3:
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3"
integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==
qs@6.11.0, qs@^6.4.0, qs@^6.7.0, qs@^6.9.4:
qs@6.11.0, qs@^6.4.0, qs@^6.7.0:
version "6.11.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
@ -6276,6 +6229,11 @@ restore-cursor@^3.1.0:
onetime "^5.1.0"
signal-exit "^3.0.2"
retry@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b"
integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==
reusify@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
@ -6624,6 +6582,11 @@ solc@0.7.3:
semver "^5.5.0"
tmp "0.0.33"
solidity-ast@^0.4.15:
version "0.4.40"
resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.40.tgz#182709271b4e55efb34e2da934dfaa96ee0cf40b"
integrity sha512-M8uLBT2jgFB7B0iVAC5a2l71J8vim7aEm03AZkaHbDqyrl1pE+i5PriMEw6WlwGfHp3/Ym7cn9BqvVLQgRk+Yw==
solidity-comments-extractor@^0.0.7:
version "0.0.7"
resolved "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz#99d8f1361438f84019795d928b931f4e5c39ca19"
@ -7188,11 +7151,6 @@ universalify@^0.1.0:
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66"
integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==
universalify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
unixify@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unixify/-/unixify-1.0.0.tgz#3a641c8c2ffbce4da683a5c70f03a462940c2090"
@ -7906,8 +7864,3 @@ yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
zksync-web3@^0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/zksync-web3/-/zksync-web3-0.8.1.tgz#db289d8f6caf61f4d5ddc471fa3448d93208dc14"
integrity sha512-1A4aHPQ3MyuGjpv5X/8pVEN+MdZqMjfVmiweQSRjOlklXYu65wT9BGEOtCmMs5d3gIvLp4ssfTeuR5OCKOD2kw==