From 0b9949166e29955015fe0ef6a6642a5685fb9f38 Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Thu, 6 Oct 2022 15:13:49 +0200 Subject: [PATCH 1/9] temporary commit --- contracts/mock/ExampleERC721.sol | 27 ++++++++++ contracts/modules/Wallet/SharedWallet.sol | 38 ++++++++++++++ test/08-SharedWallet.test.ts | 64 +++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 contracts/mock/ExampleERC721.sol create mode 100644 contracts/modules/Wallet/SharedWallet.sol create mode 100644 test/08-SharedWallet.test.ts diff --git a/contracts/mock/ExampleERC721.sol b/contracts/mock/ExampleERC721.sol new file mode 100644 index 0000000..71576bc --- /dev/null +++ b/contracts/mock/ExampleERC721.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.7.6; + +import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import "@openzeppelin/contracts/utils/Counters.sol"; + +contract ExampleERC721 is ERC721 { + + using Counters for Counters.Counter; + + Counters.Counter private _tokenId; + + constructor(string memory baseURI_) ERC721('ExampleERC721', 'EX721') { + _setBaseURI(baseURI_); + } + + function mint(address to) public { + uint256 tokenId = _tokenId.current(); + _tokenId.increment(); + _safeMint(to, tokenId); + } + + function getLastTokenId() public view returns (uint256) { + return _tokenId.current(); + } +} diff --git a/contracts/modules/Wallet/SharedWallet.sol b/contracts/modules/Wallet/SharedWallet.sol new file mode 100644 index 0000000..7e13f1f --- /dev/null +++ b/contracts/modules/Wallet/SharedWallet.sol @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.7.6; + +import '@openzeppelin/contracts/access/Ownable.sol'; +import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; +import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; + +contract SharedWallet is Ownable { + using SafeERC20 for IERC20; + + /** + * @param _owner Address of the Owner contract. + */ + constructor(address _owner) { + transferOwnership(_owner); + } + + function approveERC20(address _tokenAddress, address _address, uint256 _amount) public onlyOwner { + IERC20(_tokenAddress).approve(_address, _amount); + } + + function approveERC721(address _tokenAddress, address _address, uint256 _tokenId) public onlyOwner { + IERC721(_tokenAddress).approve(_address, _tokenId); + } + + function transferERC20(address _tokenAddress, address _to, uint256 _amount) public onlyOwner { + IERC20 erc20Token = IERC20(_tokenAddress); + address owner = owner(); + require(erc20Token.balanceOf(owner) >= _amount, 'INSUFFICIENT BALANCE'); + erc20Token.safeTransferFrom(owner, _to, _amount); + } + + function transferERC721(address _tokenAddress, address _to, uint256 _tokenId) public onlyOwner { + address owner = owner(); + IERC721 erc721Token = IERC721(_tokenAddress); + erc721Token.safeTransferFrom(owner, _to, _tokenId); + } +} \ No newline at end of file diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts new file mode 100644 index 0000000..a2c391e --- /dev/null +++ b/test/08-SharedWallet.test.ts @@ -0,0 +1,64 @@ +import { expect } from 'chai'; +import { Contract, Signer } from 'ethers'; +import { ethers } from 'hardhat'; + +describe('SharedWallet TEST', function () { + let owner: Signer, user: Signer, user2: Signer, erc20: Contract, erc721: Contract, sharedWallet: Contract; + + before(async function () { + [owner, user, user2] = await ethers.getSigners(); + + const MockTokenContract = await ethers.getContractFactory('LimitedSupplyToken'); + erc20 = await MockTokenContract.deploy( + 'ExampleERC20', + 'EX20', + await user.getAddress(), + ethers.utils.parseEther('10'), + ); + await erc20.deployed(); + console.log('MockTokenContract DEPLOYED'); + + const MockERC721Contract = await ethers.getContractFactory('NonFungibleToken'); + erc721 = await MockERC721Contract.deploy('ExampleERC721', 'EX721', 'baseURI', await user.getAddress()); + await erc721.deployed(); + console.log('MockERC721Contract DEPLOYED'); + + const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); + sharedWallet = await SharedWalletContract.deploy(await owner.getAddress()); + await sharedWallet.deployed(); + console.log('SharedWallet DEPLOYED'); + }); + + it('Should approveERC20', async function () { + const amount = ethers.utils.parseEther('1'); + const receiverAddress = await user2.getAddress(); + + const tx = await sharedWallet.approveERC20(erc20.address, receiverAddress, amount); + await tx.wait(); + + expect(await erc20.allowance(sharedWallet.address, receiverAddress)).to.equal(amount); + }); + + it('Should transferERC20', async function () { + const amount = ethers.utils.parseEther('1'); + const receiverAddress = await user.getAddress(); + let tx = await erc20.connect(user).approve(sharedWallet.address, amount); + await tx.wait(); + tx = await sharedWallet.transferERC20(erc721.address, receiverAddress, amount); + await tx.wait(); + + expect(await erc20.balanceOf(receiverAddress)).to.equal(amount); + }); + + it('Should approveERC721', async function () { + const ownerAddress = await owner.getAddress(); + const receiverAddress = await user.getAddress(); + let tx = await erc721.mint(ownerAddress, 'tokenURI'); + await tx.wait(); + const tokenId = 1; + tx = await sharedWallet.approveERC721(erc721.address, receiverAddress, tokenId); + await tx.wait(); + + expect(await erc721.getApproved(tokenId)).to.equal(receiverAddress); + }); +}); From d546415423086574eecaa4ddb6d5177ac097ee72 Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Thu, 6 Oct 2022 18:20:24 +0200 Subject: [PATCH 2/9] implemented @openzeppelin/contracts-upgradeable --- contracts/modules/Wallet/SharedWallet.sol | 21 +- hardhat.config.ts | 43 +- package-lock.json | 862 +++++++++++++++++++++- package.json | 4 +- test/08-SharedWallet.test.ts | 40 +- 5 files changed, 920 insertions(+), 50 deletions(-) diff --git a/contracts/modules/Wallet/SharedWallet.sol b/contracts/modules/Wallet/SharedWallet.sol index 7e13f1f..a23e222 100644 --- a/contracts/modules/Wallet/SharedWallet.sol +++ b/contracts/modules/Wallet/SharedWallet.sol @@ -1,18 +1,19 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.7.6; +pragma solidity ^0.8.2; -import '@openzeppelin/contracts/access/Ownable.sol'; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; -contract SharedWallet is Ownable { +contract SharedWallet is Initializable, OwnableUpgradeable { using SafeERC20 for IERC20; - + /** * @param _owner Address of the Owner contract. */ - constructor(address _owner) { - transferOwnership(_owner); + function initialize(_owner) public initializer { + transferOwnership(_owner); } function approveERC20(address _tokenAddress, address _address, uint256 _amount) public onlyOwner { @@ -25,14 +26,12 @@ contract SharedWallet is Ownable { function transferERC20(address _tokenAddress, address _to, uint256 _amount) public onlyOwner { IERC20 erc20Token = IERC20(_tokenAddress); - address owner = owner(); - require(erc20Token.balanceOf(owner) >= _amount, 'INSUFFICIENT BALANCE'); - erc20Token.safeTransferFrom(owner, _to, _amount); + require(erc20Token.balanceOf(msg.sender) >= _amount, 'INSUFFICIENT BALANCE'); + erc20Token.safeTransferFrom(msg.sender, _to, _amount); } function transferERC721(address _tokenAddress, address _to, uint256 _tokenId) public onlyOwner { - address owner = owner(); IERC721 erc721Token = IERC721(_tokenAddress); - erc721Token.safeTransferFrom(owner, _to, _tokenId); + erc721Token.safeTransferFrom(msg.sender, _to, _tokenId); } } \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 0fc96df..5e7f363 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -15,13 +15,44 @@ const POLYGON_PRIVATE_KEY_DEV = process.env.POLYGON_PRIVATE_KEY_DEV || ''; const config: HardhatUserConfig = { defaultNetwork: 'hardhat', solidity: { - version: '0.7.6', - settings: { - optimizer: { - enabled: true, - runs: 200, + compilers: [ + { + version: '0.7.6', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, }, - }, + { + version: '0.8.0', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + { + version: '0.8.1', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + { + version: '0.8.2', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + ], }, namedAccounts: { owner: { diff --git a/package-lock.json b/package-lock.json index 9a53191..2a7af31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,10 +10,12 @@ "license": "ISC", "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.1", - "@nomiclabs/hardhat-etherscan": "^2.1.1", + "@nomiclabs/hardhat-etherscan": "^3.1.0", "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/contracts": "^3.3.0", + "@openzeppelin/contracts-upgradeable": "^4.8.0-rc.1", + "@openzeppelin/hardhat-upgrades": "^1.21.0", "@types/chai": "^4.3.1", "@types/mocha": "^9.1.1", "@types/node": "^18.6.4", @@ -2045,18 +2047,21 @@ } }, "node_modules/@nomiclabs/hardhat-etherscan": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.1.tgz", - "integrity": "sha512-8TNUFsO5DpAfwNlXMDhcEtFAMOYsVNaQL2vq5vuCD45kUKBgL8H21++zOk231ha9D7LQWBMCIg7A7iPxw6Jwmg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.0.tgz", + "integrity": "sha512-JroYgfN1AlYFkQTQ3nRwFi4o8NtZF7K/qFR2dxDUgHbCtIagkUseca9L4E/D2ScUm4XT40+8PbCdqZi+XmHyQA==", "dev": true, "dependencies": { - "@ethersproject/abi": "^5.0.2", + "@ethersproject/abi": "^5.1.2", "@ethersproject/address": "^5.0.2", "cbor": "^5.0.2", + "chalk": "^2.4.2", "debug": "^4.1.1", "fs-extra": "^7.0.1", - "node-fetch": "^2.6.0", - "semver": "^6.3.0" + "lodash": "^4.17.11", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.4.0" }, "peerDependencies": { "hardhat": "^2.0.4" @@ -2102,6 +2107,18 @@ "semver": "bin/semver.js" } }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/undici": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.11.0.tgz", + "integrity": "sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==", + "dev": true, + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=12.18" + } + }, "node_modules/@nomiclabs/hardhat-waffle": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-waffle/-/hardhat-waffle-2.0.1.tgz", @@ -2137,6 +2154,248 @@ "integrity": "sha512-AemZEsQYtUp1WRkcmZm1div5ORfTpLquLaziCIrSagjxyKdmObxuaY1yjQ5SHFMctR8rLwp706NXTbiIRJg7pw==", "dev": true }, + "node_modules/@openzeppelin/contracts-upgradeable": { + "version": "4.8.0-rc.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.0-rc.1.tgz", + "integrity": "sha512-yywl0OC8ZGyRLDf0hQqGt2qtm5DZcDf6CggfE+J0bNw2mF6ySaXW6lovAZwXI/frtevUGog4WKNm6EPXtpoh3A==", + "dev": true + }, + "node_modules/@openzeppelin/hardhat-upgrades": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.21.0.tgz", + "integrity": "sha512-Kwl7IN0Hlhj4HluMTTl0DrtU90OI/Q6rG3sAyd2pv3fababe9EuZqs9DydOlkWM45JwTzC+eBzX3TgHsqI13eA==", + "dev": true, + "dependencies": { + "@openzeppelin/upgrades-core": "^1.20.0", + "chalk": "^4.1.0", + "debug": "^4.1.1", + "proper-lockfile": "^4.1.1" + }, + "bin": { + "migrate-oz-cli-project": "dist/scripts/migrate-oz-cli-project.js" + }, + "peerDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.1.0", + "ethers": "^5.0.5", + "hardhat": "^2.0.2" + }, + "peerDependenciesMeta": { + "@nomiclabs/harhdat-etherscan": { + "optional": true + } + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openzeppelin/upgrades-core": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.20.1.tgz", + "integrity": "sha512-GXvqLkMNY1dGj9BAIXiqYjdj/qgpoeTed+pH2OL4UOqMlxIh8yIYdkLE9wOWiUVVr0rhUGqaoaJ9NeFLlVzBQQ==", + "dev": true, + "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" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/@openzeppelin/upgrades-core/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/@resolver-engine/core": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz", @@ -2932,6 +3191,15 @@ "node": "*" } }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/async": { "version": "2.6.3", "resolved": "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz", @@ -3354,6 +3622,18 @@ "node-gyp-build": "^4.2.0" } }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -3762,6 +4042,12 @@ "integrity": "sha1-aDfD+2d62ZM9HPukLdFNURfWs54= sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", "dev": true }, + "node_modules/compare-versions": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.1.tgz", + "integrity": "sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ==", + "dev": true + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz", @@ -17423,6 +17709,12 @@ "dev": true, "peer": true }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -18340,6 +18632,7 @@ "resolved": "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz", "integrity": "sha1-BFvTI2Mfdu0uK1VXM5RBa2OaAFI= sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", "dev": true, + "peer": true, "engines": { "node": "4.x || >=6.0.0" } @@ -19216,6 +19509,17 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -19607,6 +19911,15 @@ "lowercase-keys": "^1.0.0" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -19873,9 +20186,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "optional": true, - "peer": true + "dev": true }, "node_modules/simple-concat": { "version": "1.0.1", @@ -19917,6 +20228,65 @@ "node": ">=8" } }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/solc": { "version": "0.7.3", "resolved": "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz", @@ -19940,6 +20310,12 @@ "node": ">=8.0.0" } }, + "node_modules/solidity-ast": { + "version": "0.4.35", + "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.35.tgz", + "integrity": "sha512-F5bTDLh3rmDxRmLSrs3qt3nvxJprWSEkS7h2KmuXDx7XTfJ6ZKVTV1rtPIYCqJAuPsU/qa8YUeFn7jdOAZcTPA==", + "dev": true + }, "node_modules/solidity-comments-extractor": { "version": "0.0.7", "resolved": "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", @@ -20069,6 +20445,15 @@ "node": ">=0.10.0" } }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -20326,6 +20711,94 @@ "get-port": "^3.1.0" } }, + "node_modules/table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/table/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/table/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/tar": { "version": "4.4.19", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", @@ -23761,18 +24234,21 @@ "requires": {} }, "@nomiclabs/hardhat-etherscan": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-2.1.1.tgz", - "integrity": "sha512-8TNUFsO5DpAfwNlXMDhcEtFAMOYsVNaQL2vq5vuCD45kUKBgL8H21++zOk231ha9D7LQWBMCIg7A7iPxw6Jwmg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.0.tgz", + "integrity": "sha512-JroYgfN1AlYFkQTQ3nRwFi4o8NtZF7K/qFR2dxDUgHbCtIagkUseca9L4E/D2ScUm4XT40+8PbCdqZi+XmHyQA==", "dev": true, "requires": { - "@ethersproject/abi": "^5.0.2", + "@ethersproject/abi": "^5.1.2", "@ethersproject/address": "^5.0.2", "cbor": "^5.0.2", + "chalk": "^2.4.2", "debug": "^4.1.1", "fs-extra": "^7.0.1", - "node-fetch": "^2.6.0", - "semver": "^6.3.0" + "lodash": "^4.17.11", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.4.0" }, "dependencies": { "debug": { @@ -23800,6 +24276,15 @@ "resolved": "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz", "integrity": "sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0= sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + }, + "undici": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.11.0.tgz", + "integrity": "sha512-oWjWJHzFet0Ow4YZBkyiJwiK5vWqEYoH7BINzJAJOLedZ++JpAlCbUktW2GQ2DS2FpKmxD/JMtWUUWl1BtghGw==", + "dev": true, + "requires": { + "busboy": "^1.6.0" + } } } }, @@ -23828,6 +24313,174 @@ "integrity": "sha512-AemZEsQYtUp1WRkcmZm1div5ORfTpLquLaziCIrSagjxyKdmObxuaY1yjQ5SHFMctR8rLwp706NXTbiIRJg7pw==", "dev": true }, + "@openzeppelin/contracts-upgradeable": { + "version": "4.8.0-rc.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.8.0-rc.1.tgz", + "integrity": "sha512-yywl0OC8ZGyRLDf0hQqGt2qtm5DZcDf6CggfE+J0bNw2mF6ySaXW6lovAZwXI/frtevUGog4WKNm6EPXtpoh3A==", + "dev": true + }, + "@openzeppelin/hardhat-upgrades": { + "version": "1.21.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.21.0.tgz", + "integrity": "sha512-Kwl7IN0Hlhj4HluMTTl0DrtU90OI/Q6rG3sAyd2pv3fababe9EuZqs9DydOlkWM45JwTzC+eBzX3TgHsqI13eA==", + "dev": true, + "requires": { + "@openzeppelin/upgrades-core": "^1.20.0", + "chalk": "^4.1.0", + "debug": "^4.1.1", + "proper-lockfile": "^4.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@openzeppelin/upgrades-core": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.20.1.tgz", + "integrity": "sha512-GXvqLkMNY1dGj9BAIXiqYjdj/qgpoeTed+pH2OL4UOqMlxIh8yIYdkLE9wOWiUVVr0rhUGqaoaJ9NeFLlVzBQQ==", + "dev": true, + "requires": { + "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" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "cbor": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", + "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "dev": true, + "requires": { + "nofilter": "^3.1.0" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "@resolver-engine/core": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@resolver-engine/core/-/core-0.3.3.tgz", @@ -24529,6 +25182,12 @@ "integrity": "sha1-5gtrDo8wG9l+U3UhW9pAbIURjAs= sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true }, + "astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true + }, "async": { "version": "2.6.3", "resolved": "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz", @@ -24899,6 +25558,15 @@ "node-gyp-build": "^4.2.0" } }, + "busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dev": true, + "requires": { + "streamsearch": "^1.1.0" + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -25222,6 +25890,12 @@ "integrity": "sha1-aDfD+2d62ZM9HPukLdFNURfWs54= sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", "dev": true }, + "compare-versions": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-5.0.1.tgz", + "integrity": "sha512-v8Au3l0b+Nwkp4G142JcgJFh1/TUhdxut7wzD1Nq1dyp5oa3tXaqb03EXOAB6jS4gMlalkjAUPZBMiAfKUixHQ==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz", @@ -36055,6 +36729,12 @@ "dev": true, "peer": true }, + "lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true + }, "log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", @@ -36773,7 +37453,8 @@ "version": "2.6.1", "resolved": "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz", "integrity": "sha1-BFvTI2Mfdu0uK1VXM5RBa2OaAFI= sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", - "dev": true + "dev": true, + "peer": true }, "node-gyp-build": { "version": "4.3.0", @@ -37442,6 +38123,17 @@ "iterate-value": "^1.0.0" } }, + "proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -37761,6 +38453,12 @@ "lowercase-keys": "^1.0.0" } }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -37969,9 +38667,7 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "optional": true, - "peer": true + "dev": true }, "simple-concat": { "version": "1.0.1", @@ -37996,6 +38692,49 @@ "integrity": "sha1-ZTm+hwwWWtvVJAIg2+Nh8bxNRjQ= sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + } + } + }, "solc": { "version": "0.7.3", "resolved": "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz", @@ -38013,6 +38752,12 @@ "tmp": "0.0.33" } }, + "solidity-ast": { + "version": "0.4.35", + "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.35.tgz", + "integrity": "sha512-F5bTDLh3rmDxRmLSrs3qt3nvxJprWSEkS7h2KmuXDx7XTfJ6ZKVTV1rtPIYCqJAuPsU/qa8YUeFn7jdOAZcTPA==", + "dev": true + }, "solidity-comments-extractor": { "version": "0.0.7", "resolved": "https://registry.yarnpkg.com/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz", @@ -38123,6 +38868,12 @@ "integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=", "dev": true }, + "streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "dev": true + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -38334,6 +39085,77 @@ "get-port": "^3.1.0" } }, + "table": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.0.tgz", + "integrity": "sha512-s/fitrbVeEyHKFa7mFdkuQMWlH1Wgw/yEXMt5xACT4ZpzWFluehAxRtUUQKPuWhaLAWhFcVx6w3oC8VKaUfPGA==", + "dev": true, + "requires": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ajv": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz", + "integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, "tar": { "version": "4.4.19", "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", diff --git a/package.json b/package.json index 7e916b0..d115763 100644 --- a/package.json +++ b/package.json @@ -61,10 +61,12 @@ }, "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.1", - "@nomiclabs/hardhat-etherscan": "^2.1.1", + "@nomiclabs/hardhat-etherscan": "^3.1.0", "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/contracts": "^3.3.0", + "@openzeppelin/hardhat-upgrades": "^1.21.0", + "@openzeppelin/contracts-upgradeable": "^4.8.0-rc.1", "@types/chai": "^4.3.1", "@types/mocha": "^9.1.1", "@types/node": "^18.6.4", diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts index a2c391e..9b524c2 100644 --- a/test/08-SharedWallet.test.ts +++ b/test/08-SharedWallet.test.ts @@ -1,6 +1,6 @@ import { expect } from 'chai'; import { Contract, Signer } from 'ethers'; -import { ethers } from 'hardhat'; +import { ethers, upgrades } from 'hardhat'; describe('SharedWallet TEST', function () { let owner: Signer, user: Signer, user2: Signer, erc20: Contract, erc721: Contract, sharedWallet: Contract; @@ -8,15 +8,15 @@ describe('SharedWallet TEST', function () { before(async function () { [owner, user, user2] = await ethers.getSigners(); - const MockTokenContract = await ethers.getContractFactory('LimitedSupplyToken'); - erc20 = await MockTokenContract.deploy( + const MockERC20TokenContract = await ethers.getContractFactory('LimitedSupplyToken'); + erc20 = await MockERC20TokenContract.deploy( 'ExampleERC20', 'EX20', await user.getAddress(), ethers.utils.parseEther('10'), ); await erc20.deployed(); - console.log('MockTokenContract DEPLOYED'); + console.log('MockERC20TokenContract DEPLOYED'); const MockERC721Contract = await ethers.getContractFactory('NonFungibleToken'); erc721 = await MockERC721Contract.deploy('ExampleERC721', 'EX721', 'baseURI', await user.getAddress()); @@ -24,7 +24,7 @@ describe('SharedWallet TEST', function () { console.log('MockERC721Contract DEPLOYED'); const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); - sharedWallet = await SharedWalletContract.deploy(await owner.getAddress()); + sharedWallet = await upgrades.deployProxy(SharedWalletContract, await user.getAddress()); await sharedWallet.deployed(); console.log('SharedWallet DEPLOYED'); }); @@ -33,7 +33,7 @@ describe('SharedWallet TEST', function () { const amount = ethers.utils.parseEther('1'); const receiverAddress = await user2.getAddress(); - const tx = await sharedWallet.approveERC20(erc20.address, receiverAddress, amount); + const tx = await sharedWallet.connect(user).approveERC20(erc20.address, receiverAddress, amount); await tx.wait(); expect(await erc20.allowance(sharedWallet.address, receiverAddress)).to.equal(amount); @@ -41,24 +41,40 @@ describe('SharedWallet TEST', function () { it('Should transferERC20', async function () { const amount = ethers.utils.parseEther('1'); - const receiverAddress = await user.getAddress(); + const receiverAddress = await user2.getAddress(); let tx = await erc20.connect(user).approve(sharedWallet.address, amount); await tx.wait(); - tx = await sharedWallet.transferERC20(erc721.address, receiverAddress, amount); + tx = await sharedWallet.connect(user).transferERC20(erc20.address, receiverAddress, amount); await tx.wait(); expect(await erc20.balanceOf(receiverAddress)).to.equal(amount); }); it('Should approveERC721', async function () { - const ownerAddress = await owner.getAddress(); - const receiverAddress = await user.getAddress(); - let tx = await erc721.mint(ownerAddress, 'tokenURI'); + const mintAddress = await user.getAddress(); + const receiverAddress = await user2.getAddress(); + + let tx = await erc721.connect(user).mint(mintAddress, 'tokenURI'); await tx.wait(); const tokenId = 1; - tx = await sharedWallet.approveERC721(erc721.address, receiverAddress, tokenId); + tx = await sharedWallet.connect(user).approveERC721(erc721.address, receiverAddress, tokenId); await tx.wait(); expect(await erc721.getApproved(tokenId)).to.equal(receiverAddress); }); + + it('Should transferERC721', async function () { + const mintAddress = await user.getAddress(); + const receiverAddress = await user2.getAddress(); + + let tx = await erc721.connect(user).mint(mintAddress, 'tokenURI'); + await tx.wait(); + const tokenId = 1; + tx = await erc721.connect(user).approve(sharedWallet.address, tokenId); + await tx.wait(); + tx = await sharedWallet.connect(user).transferERC721(erc721.address, receiverAddress, tokenId); + await tx.wait(); + + expect(await erc721.ownerOf(tokenId)).to.equal(receiverAddress); + }); }); From b7c27630b4a18a98374e51b431b020c7ac06a18f Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Wed, 12 Oct 2022 15:21:09 +0200 Subject: [PATCH 3/9] installed @openzeppelin/contracts-v4.7.3 --- contracts/modules/Wallet/SharedWallet.sol | 8 ++++---- hardhat.config.ts | 2 +- package-lock.json | 14 ++++++++++++++ package.json | 1 + test/08-SharedWallet.test.ts | 2 +- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/contracts/modules/Wallet/SharedWallet.sol b/contracts/modules/Wallet/SharedWallet.sol index a23e222..b9384eb 100644 --- a/contracts/modules/Wallet/SharedWallet.sol +++ b/contracts/modules/Wallet/SharedWallet.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.2; +pragma solidity ^0.8.0; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import '@openzeppelin/contracts/token/ERC20/SafeERC20.sol'; -import '@openzeppelin/contracts/token/ERC721/IERC721.sol'; +import '@openzeppelin/contracts-v4.7.3/token/ERC20/utils/SafeERC20.sol'; +import '@openzeppelin/contracts-v4.7.3/token/ERC721/IERC721.sol'; contract SharedWallet is Initializable, OwnableUpgradeable { using SafeERC20 for IERC20; @@ -12,7 +12,7 @@ contract SharedWallet is Initializable, OwnableUpgradeable { /** * @param _owner Address of the Owner contract. */ - function initialize(_owner) public initializer { + function initialize(address _owner) public initializer { transferOwnership(_owner); } diff --git a/hardhat.config.ts b/hardhat.config.ts index 5e7f363..d017e32 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -5,7 +5,7 @@ import '@nomiclabs/hardhat-etherscan'; import '@nomiclabs/hardhat-web3'; import 'hardhat-gas-reporter'; import 'hardhat-deploy'; - +import '@openzeppelin/hardhat-upgrades'; dotenv.config(); const INFURA_PROJECT_ID = process.env.INFURA_PROJECT_ID || ''; diff --git a/package-lock.json b/package-lock.json index 2a7af31..5b2f56e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/contracts": "^3.3.0", "@openzeppelin/contracts-upgradeable": "^4.8.0-rc.1", + "@openzeppelin/contracts-v4.7.3": "npm:@openzeppelin/contracts@^4.7.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@types/chai": "^4.3.1", "@types/mocha": "^9.1.1", @@ -2160,6 +2161,13 @@ "integrity": "sha512-yywl0OC8ZGyRLDf0hQqGt2qtm5DZcDf6CggfE+J0bNw2mF6ySaXW6lovAZwXI/frtevUGog4WKNm6EPXtpoh3A==", "dev": true }, + "node_modules/@openzeppelin/contracts-v4.7.3": { + "name": "@openzeppelin/contracts", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", + "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==", + "dev": true + }, "node_modules/@openzeppelin/hardhat-upgrades": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.21.0.tgz", @@ -24319,6 +24327,12 @@ "integrity": "sha512-yywl0OC8ZGyRLDf0hQqGt2qtm5DZcDf6CggfE+J0bNw2mF6ySaXW6lovAZwXI/frtevUGog4WKNm6EPXtpoh3A==", "dev": true }, + "@openzeppelin/contracts-v4.7.3": { + "version": "npm:@openzeppelin/contracts@4.7.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", + "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==", + "dev": true + }, "@openzeppelin/hardhat-upgrades": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.21.0.tgz", diff --git a/package.json b/package.json index d115763..9effcd7 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/contracts": "^3.3.0", + "@openzeppelin/contracts-v4.7.3": "npm:@openzeppelin/contracts@^4.7.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@openzeppelin/contracts-upgradeable": "^4.8.0-rc.1", "@types/chai": "^4.3.1", diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts index 9b524c2..3d6eed4 100644 --- a/test/08-SharedWallet.test.ts +++ b/test/08-SharedWallet.test.ts @@ -24,7 +24,7 @@ describe('SharedWallet TEST', function () { console.log('MockERC721Contract DEPLOYED'); const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); - sharedWallet = await upgrades.deployProxy(SharedWalletContract, await user.getAddress()); + sharedWallet = await upgrades.deployProxy(SharedWalletContract, [await user.getAddress()]); await sharedWallet.deployed(); console.log('SharedWallet DEPLOYED'); }); From 5e1e33ab424ca7598ad28b8a1f58202653c6e29f Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Wed, 12 Oct 2022 19:24:26 +0200 Subject: [PATCH 4/9] created new functions --- .openzeppelin/unknown-31337.json | 151 ++++++++++++++++++++++ contracts/modules/Wallet/SharedWallet.sol | 65 +++++++--- hardhat.config.ts | 9 ++ package-lock.json | 14 -- package.json | 1 - test/08-SharedWallet.test.ts | 56 +++++--- test/utils.ts | 1 + 7 files changed, 248 insertions(+), 49 deletions(-) create mode 100644 .openzeppelin/unknown-31337.json diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json new file mode 100644 index 0000000..f6b899b --- /dev/null +++ b/.openzeppelin/unknown-31337.json @@ -0,0 +1,151 @@ +{ + "manifestVersion": "3.2", + "admin": { + "address": "0xb63564A81D5d4004F4f22E9aB074cE25540B0C26", + "txHash": "0xb50d471597a4174b783d339ea368a8ed05dbd631d4a241ad95e9a9c22824d145" + }, + "proxies": [ + { + "address": "0xBceA63C5A6dDaC14853854D10f4b2AbAefed2C61", + "txHash": "0xc0c96dc0926da7fd52c8bfa6de4c10cb9151a9b61bcac8a2f529ac72f962e15a", + "kind": "transparent" + }, + { + "address": "0x50aF0922d65D04D87d810048Dc640E2474eBfbd9", + "txHash": "0xeaf74320d4a412217e94605eea724ef15d7f146e6adcb24fd30ea22d9ba77dfa", + "kind": "transparent" + } + ], + "impls": { + "1be117df27ae37206e8eb90713306e7623c7ea0f9a3c866624fa29c68a84f0da": { + "address": "0x055cBfeD6df4AFE2452b18fd3D2592D1795592b4", + "txHash": "0x493c96c515d349b4bf0bc45975165d677069f4fd07eea8ca6362493d13561604", + "layout": { + "solcVersion": "0.8.6", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_bytes32,t_struct(RoleData)34_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)34_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(RoleData)34_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } + } + } +} diff --git a/contracts/modules/Wallet/SharedWallet.sol b/contracts/modules/Wallet/SharedWallet.sol index b9384eb..fde0b00 100644 --- a/contracts/modules/Wallet/SharedWallet.sol +++ b/contracts/modules/Wallet/SharedWallet.sol @@ -1,37 +1,68 @@ // SPDX-License-Identifier: Apache-2.0 -pragma solidity ^0.8.0; +pragma solidity ^0.8.6; import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import '@openzeppelin/contracts-v4.7.3/token/ERC20/utils/SafeERC20.sol'; -import '@openzeppelin/contracts-v4.7.3/token/ERC721/IERC721.sol'; +import '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol'; +import 'hardhat/console.sol'; -contract SharedWallet is Initializable, OwnableUpgradeable { - using SafeERC20 for IERC20; +contract SharedWallet is Initializable, AccessControlUpgradeable, OwnableUpgradeable { + using SafeERC20Upgradeable for IERC20Upgradeable; + bytes32 public constant MANAGER_ROLE = keccak256('MANAGER_ROLE'); + modifier onlyManager() { + require(hasRole(MANAGER_ROLE, _msgSender()), "Caller is not a manager"); + _; + } /** * @param _owner Address of the Owner contract. */ function initialize(address _owner) public initializer { - transferOwnership(_owner); + console.log('_owner', _owner); + __Ownable_init(); + transferOwnership(_owner); + _grantRole(MANAGER_ROLE, _owner); + } + + function approveERC20(address _tokenAddress, address _address, uint256 _amount) external onlyManager { + IERC20Upgradeable(_tokenAddress).approve(_address, _amount); } - function approveERC20(address _tokenAddress, address _address, uint256 _amount) public onlyOwner { - IERC20(_tokenAddress).approve(_address, _amount); + function approveERC721(address _tokenAddress, address _address, uint256 _tokenId) external onlyManager { + IERC721Upgradeable token = IERC721Upgradeable(_tokenAddress); + console.log('ownerOf shared wallet', token.ownerOf(_tokenId)); + token.approve(_address, _tokenId); } - function approveERC721(address _tokenAddress, address _address, uint256 _tokenId) public onlyOwner { - IERC721(_tokenAddress).approve(_address, _tokenId); + function transferERC20(address _tokenAddress, address _to, uint256 _amount) external onlyManager { + IERC20Upgradeable erc20Token = IERC20Upgradeable(_tokenAddress); + require(erc20Token.balanceOf(_msgSender()) >= _amount, 'INSUFFICIENT BALANCE'); + erc20Token.safeTransferFrom(_msgSender(), _to, _amount); } - function transferERC20(address _tokenAddress, address _to, uint256 _amount) public onlyOwner { - IERC20 erc20Token = IERC20(_tokenAddress); - require(erc20Token.balanceOf(msg.sender) >= _amount, 'INSUFFICIENT BALANCE'); - erc20Token.safeTransferFrom(msg.sender, _to, _amount); + function transferERC721(address _tokenAddress, address _to, uint256 _tokenId) external onlyManager { + IERC721Upgradeable erc721Token = IERC721Upgradeable(_tokenAddress); + erc721Token.safeTransferFrom(_msgSender(), _to, _tokenId); } - function transferERC721(address _tokenAddress, address _to, uint256 _tokenId) public onlyOwner { - IERC721 erc721Token = IERC721(_tokenAddress); - erc721Token.safeTransferFrom(msg.sender, _to, _tokenId); + /** + * @notice Grants a role to a given account address if sender is contract owner. + * @param role Bytes32 array representing the role. + * @param account Address of the account that is given the role. + */ + function grantRole(bytes32 role, address account) override public onlyOwner { + _grantRole(role, account); + } + + /** + * @notice Revokes the role for a given account address if sender is contract owner + * @param role Bytes32 array representing the role. + * @param account Address of the account + */ + function revokeRole(bytes32 role, address account) override public onlyOwner { + _revokeRole(role, account); } } \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index d017e32..61ff437 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -52,6 +52,15 @@ const config: HardhatUserConfig = { }, }, }, + { + version: '0.8.6', + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, ], }, namedAccounts: { diff --git a/package-lock.json b/package-lock.json index 5b2f56e..2a7af31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,7 +15,6 @@ "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/contracts": "^3.3.0", "@openzeppelin/contracts-upgradeable": "^4.8.0-rc.1", - "@openzeppelin/contracts-v4.7.3": "npm:@openzeppelin/contracts@^4.7.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@types/chai": "^4.3.1", "@types/mocha": "^9.1.1", @@ -2161,13 +2160,6 @@ "integrity": "sha512-yywl0OC8ZGyRLDf0hQqGt2qtm5DZcDf6CggfE+J0bNw2mF6ySaXW6lovAZwXI/frtevUGog4WKNm6EPXtpoh3A==", "dev": true }, - "node_modules/@openzeppelin/contracts-v4.7.3": { - "name": "@openzeppelin/contracts", - "version": "4.7.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", - "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==", - "dev": true - }, "node_modules/@openzeppelin/hardhat-upgrades": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.21.0.tgz", @@ -24327,12 +24319,6 @@ "integrity": "sha512-yywl0OC8ZGyRLDf0hQqGt2qtm5DZcDf6CggfE+J0bNw2mF6ySaXW6lovAZwXI/frtevUGog4WKNm6EPXtpoh3A==", "dev": true }, - "@openzeppelin/contracts-v4.7.3": { - "version": "npm:@openzeppelin/contracts@4.7.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", - "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==", - "dev": true - }, "@openzeppelin/hardhat-upgrades": { "version": "1.21.0", "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.21.0.tgz", diff --git a/package.json b/package.json index 9effcd7..d115763 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,6 @@ "@nomiclabs/hardhat-waffle": "^2.0.1", "@nomiclabs/hardhat-web3": "^2.0.0", "@openzeppelin/contracts": "^3.3.0", - "@openzeppelin/contracts-v4.7.3": "npm:@openzeppelin/contracts@^4.7.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", "@openzeppelin/contracts-upgradeable": "^4.8.0-rc.1", "@types/chai": "^4.3.1", diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts index 3d6eed4..add4309 100644 --- a/test/08-SharedWallet.test.ts +++ b/test/08-SharedWallet.test.ts @@ -1,30 +1,38 @@ import { expect } from 'chai'; import { Contract, Signer } from 'ethers'; +import { getAddress } from 'ethers/lib/utils'; import { ethers, upgrades } from 'hardhat'; +import { MANAGER_ROLE } from './utils'; describe('SharedWallet TEST', function () { - let owner: Signer, user: Signer, user2: Signer, erc20: Contract, erc721: Contract, sharedWallet: Contract; + let owner, + user: Signer, + user2: Signer, + erc20: Contract, + erc721: Contract, + sharedWallet: Contract, + contractOwnerAddress: string; before(async function () { - [owner, user, user2] = await ethers.getSigners(); + [owner, user2] = await ethers.getSigners(); const MockERC20TokenContract = await ethers.getContractFactory('LimitedSupplyToken'); erc20 = await MockERC20TokenContract.deploy( 'ExampleERC20', 'EX20', - await user.getAddress(), + await owner.getAddress(), ethers.utils.parseEther('10'), ); await erc20.deployed(); console.log('MockERC20TokenContract DEPLOYED'); - + contractOwnerAddress = getAddress(await owner.getAddress()); const MockERC721Contract = await ethers.getContractFactory('NonFungibleToken'); - erc721 = await MockERC721Contract.deploy('ExampleERC721', 'EX721', 'baseURI', await user.getAddress()); + erc721 = await MockERC721Contract.deploy('ExampleERC721', 'EX721', 'baseURI', contractOwnerAddress); await erc721.deployed(); console.log('MockERC721Contract DEPLOYED'); const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); - sharedWallet = await upgrades.deployProxy(SharedWalletContract, [await user.getAddress()]); + sharedWallet = await upgrades.deployProxy(SharedWalletContract, [contractOwnerAddress]); await sharedWallet.deployed(); console.log('SharedWallet DEPLOYED'); }); @@ -33,7 +41,7 @@ describe('SharedWallet TEST', function () { const amount = ethers.utils.parseEther('1'); const receiverAddress = await user2.getAddress(); - const tx = await sharedWallet.connect(user).approveERC20(erc20.address, receiverAddress, amount); + const tx = await sharedWallet.approveERC20(erc20.address, receiverAddress, amount); await tx.wait(); expect(await erc20.allowance(sharedWallet.address, receiverAddress)).to.equal(amount); @@ -42,39 +50,53 @@ describe('SharedWallet TEST', function () { it('Should transferERC20', async function () { const amount = ethers.utils.parseEther('1'); const receiverAddress = await user2.getAddress(); - let tx = await erc20.connect(user).approve(sharedWallet.address, amount); + let tx = await erc20.approve(sharedWallet.address, amount); await tx.wait(); - tx = await sharedWallet.connect(user).transferERC20(erc20.address, receiverAddress, amount); + tx = await sharedWallet.transferERC20(erc20.address, receiverAddress, amount); await tx.wait(); expect(await erc20.balanceOf(receiverAddress)).to.equal(amount); }); it('Should approveERC721', async function () { - const mintAddress = await user.getAddress(); + const tokenId = 1; const receiverAddress = await user2.getAddress(); - let tx = await erc721.connect(user).mint(mintAddress, 'tokenURI'); + let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); await tx.wait(); - const tokenId = 1; - tx = await sharedWallet.connect(user).approveERC721(erc721.address, receiverAddress, tokenId); + + console.log('ownerOf', await erc721.ownerOf(tokenId)); + tx = await sharedWallet.approveERC721(erc721.address, receiverAddress, tokenId); await tx.wait(); expect(await erc721.getApproved(tokenId)).to.equal(receiverAddress); }); it('Should transferERC721', async function () { - const mintAddress = await user.getAddress(); const receiverAddress = await user2.getAddress(); - let tx = await erc721.connect(user).mint(mintAddress, 'tokenURI'); + let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); await tx.wait(); const tokenId = 1; - tx = await erc721.connect(user).approve(sharedWallet.address, tokenId); + tx = await erc721.approve(sharedWallet.address, tokenId); await tx.wait(); - tx = await sharedWallet.connect(user).transferERC721(erc721.address, receiverAddress, tokenId); + tx = await sharedWallet.transferERC721(erc721.address, receiverAddress, tokenId); await tx.wait(); expect(await erc721.ownerOf(tokenId)).to.equal(receiverAddress); }); + + it('Should grant a Manager Role', async function () { + const receiverAddress = await user2.getAddress(); + await sharedWallet.grantRole(MANAGER_ROLE, receiverAddress); + + expect(await sharedWallet.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(true); + }); + + it('Should revoke a Manager Role', async function () { + const receiverAddress = await user2.getAddress(); + await sharedWallet.revokeRole(MANAGER_ROLE, receiverAddress); + + expect(await sharedWallet.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(false); + }); }); diff --git a/test/utils.ts b/test/utils.ts index 6eb95a8..32135cf 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -95,4 +95,5 @@ export function createUnlockDate(numMonths: number) { } export const MINTER_ROLE = keccak256(toUtf8Bytes('MINTER_ROLE')); +export const MANAGER_ROLE = keccak256(toUtf8Bytes('MANAGER_ROLE')); export const ADDRESS_ZERO = constants.AddressZero; From 7b506074371b6ec3f480176ae0b541079d4adb19 Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Wed, 12 Oct 2022 19:35:56 +0200 Subject: [PATCH 5/9] implemented upgrade test --- .openzeppelin/unknown-31337.json | 130 +++++++++++++++++++++++ contracts/mock/ExampleERC721.sol | 27 ----- contracts/mock/Wallet/SharedWalletV2.sol | 72 +++++++++++++ test/08-SharedWallet.test.ts | 49 +++++---- 4 files changed, 229 insertions(+), 49 deletions(-) delete mode 100644 contracts/mock/ExampleERC721.sol create mode 100644 contracts/mock/Wallet/SharedWalletV2.sol diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json index f6b899b..3fc39de 100644 --- a/.openzeppelin/unknown-31337.json +++ b/.openzeppelin/unknown-31337.json @@ -146,6 +146,136 @@ } } } + }, + "a1c5cebe331372a4f5706386561899d7e5fd3e949f492327a4869bca85a43c36": { + "address": "0x15FC0878406CcF4d2963235A5B1EF68C67F17Ee5", + "txHash": "0xb4184fe932416b84e55bce996424e07aece1207b2a2362553fca0b5f42309345", + "layout": { + "solcVersion": "0.8.6", + "storage": [ + { + "label": "_initialized", + "offset": 0, + "slot": "0", + "type": "t_uint8", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:62", + "retypedFrom": "bool" + }, + { + "label": "_initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:67" + }, + { + "label": "__gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "ContextUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" + }, + { + "label": "__gap", + "offset": 0, + "slot": "51", + "type": "t_array(t_uint256)50_storage", + "contract": "ERC165Upgradeable", + "src": "@openzeppelin/contracts-upgradeable/utils/introspection/ERC165Upgradeable.sol:41" + }, + { + "label": "_roles", + "offset": 0, + "slot": "101", + "type": "t_mapping(t_bytes32,t_struct(RoleData)34_storage)", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:61" + }, + { + "label": "__gap", + "offset": 0, + "slot": "102", + "type": "t_array(t_uint256)49_storage", + "contract": "AccessControlUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol:259" + }, + { + "label": "_owner", + "offset": 0, + "slot": "151", + "type": "t_address", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" + }, + { + "label": "__gap", + "offset": 0, + "slot": "152", + "type": "t_array(t_uint256)49_storage", + "contract": "OwnableUpgradeable", + "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_uint256)49_storage": { + "label": "uint256[49]", + "numberOfBytes": "1568" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_bool)": { + "label": "mapping(address => bool)", + "numberOfBytes": "32" + }, + "t_mapping(t_bytes32,t_struct(RoleData)34_storage)": { + "label": "mapping(bytes32 => struct AccessControlUpgradeable.RoleData)", + "numberOfBytes": "32" + }, + "t_struct(RoleData)34_storage": { + "label": "struct AccessControlUpgradeable.RoleData", + "members": [ + { + "label": "members", + "type": "t_mapping(t_address,t_bool)", + "offset": 0, + "slot": "0" + }, + { + "label": "adminRole", + "type": "t_bytes32", + "offset": 0, + "slot": "1" + } + ], + "numberOfBytes": "64" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "label": "uint8", + "numberOfBytes": "1" + } + } + } } } } diff --git a/contracts/mock/ExampleERC721.sol b/contracts/mock/ExampleERC721.sol deleted file mode 100644 index 71576bc..0000000 --- a/contracts/mock/ExampleERC721.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -pragma solidity ^0.7.6; - -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/utils/Counters.sol"; - -contract ExampleERC721 is ERC721 { - - using Counters for Counters.Counter; - - Counters.Counter private _tokenId; - - constructor(string memory baseURI_) ERC721('ExampleERC721', 'EX721') { - _setBaseURI(baseURI_); - } - - function mint(address to) public { - uint256 tokenId = _tokenId.current(); - _tokenId.increment(); - _safeMint(to, tokenId); - } - - function getLastTokenId() public view returns (uint256) { - return _tokenId.current(); - } -} diff --git a/contracts/mock/Wallet/SharedWalletV2.sol b/contracts/mock/Wallet/SharedWalletV2.sol new file mode 100644 index 0000000..327b357 --- /dev/null +++ b/contracts/mock/Wallet/SharedWalletV2.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.6; + +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol'; +import 'hardhat/console.sol'; + +contract SharedWalletV2 is Initializable, AccessControlUpgradeable, OwnableUpgradeable { + using SafeERC20Upgradeable for IERC20Upgradeable; + bytes32 public constant MANAGER_ROLE = keccak256('MANAGER_ROLE'); + + modifier onlyManager() { + require(hasRole(MANAGER_ROLE, _msgSender()), "Caller is not a manager"); + _; + } + /** + * @param _owner Address of the Owner contract. + */ + function initialize(address _owner) public initializer { + console.log('_owner', _owner); + __Ownable_init(); + transferOwnership(_owner); + _grantRole(MANAGER_ROLE, _owner); + } + + function approveERC20(address _tokenAddress, address _address, uint256 _amount) external onlyManager { + IERC20Upgradeable(_tokenAddress).approve(_address, _amount); + } + + function approveERC721(address _tokenAddress, address _address, uint256 _tokenId) external onlyManager { + IERC721Upgradeable token = IERC721Upgradeable(_tokenAddress); + console.log('ownerOf shared wallet', token.ownerOf(_tokenId)); + token.approve(_address, _tokenId); + } + + function transferERC20(address _tokenAddress, address _to, uint256 _amount) external onlyManager { + IERC20Upgradeable erc20Token = IERC20Upgradeable(_tokenAddress); + require(erc20Token.balanceOf(_msgSender()) >= _amount, 'INSUFFICIENT BALANCE'); + erc20Token.safeTransferFrom(_msgSender(), _to, _amount); + } + + function transferERC721(address _tokenAddress, address _to, uint256 _tokenId) external onlyManager { + IERC721Upgradeable erc721Token = IERC721Upgradeable(_tokenAddress); + erc721Token.safeTransferFrom(_msgSender(), _to, _tokenId); + } + + /** + * @notice Grants a role to a given account address if sender is contract owner. + * @param role Bytes32 array representing the role. + * @param account Address of the account that is given the role. + */ + function grantRole(bytes32 role, address account) override public onlyOwner { + _grantRole(role, account); + } + + /** + * @notice Revokes the role for a given account address if sender is contract owner + * @param role Bytes32 array representing the role. + * @param account Address of the account + */ + function revokeRole(bytes32 role, address account) override public onlyOwner { + _revokeRole(role, account); + } + + function isContractUpgraded() external pure returns(bool) { + return true; + } +} \ No newline at end of file diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts index add4309..7d7c7c8 100644 --- a/test/08-SharedWallet.test.ts +++ b/test/08-SharedWallet.test.ts @@ -7,14 +7,13 @@ import { MANAGER_ROLE } from './utils'; describe('SharedWallet TEST', function () { let owner, user: Signer, - user2: Signer, erc20: Contract, erc721: Contract, - sharedWallet: Contract, + sharedWalletProxy: Contract, contractOwnerAddress: string; before(async function () { - [owner, user2] = await ethers.getSigners(); + [owner, user] = await ethers.getSigners(); const MockERC20TokenContract = await ethers.getContractFactory('LimitedSupplyToken'); erc20 = await MockERC20TokenContract.deploy( @@ -32,27 +31,27 @@ describe('SharedWallet TEST', function () { console.log('MockERC721Contract DEPLOYED'); const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); - sharedWallet = await upgrades.deployProxy(SharedWalletContract, [contractOwnerAddress]); - await sharedWallet.deployed(); + sharedWalletProxy = await upgrades.deployProxy(SharedWalletContract, [contractOwnerAddress]); + await sharedWalletProxy.deployed(); console.log('SharedWallet DEPLOYED'); }); it('Should approveERC20', async function () { const amount = ethers.utils.parseEther('1'); - const receiverAddress = await user2.getAddress(); + const receiverAddress = await user.getAddress(); - const tx = await sharedWallet.approveERC20(erc20.address, receiverAddress, amount); + const tx = await sharedWalletProxy.approveERC20(erc20.address, receiverAddress, amount); await tx.wait(); - expect(await erc20.allowance(sharedWallet.address, receiverAddress)).to.equal(amount); + expect(await erc20.allowance(sharedWalletProxy.address, receiverAddress)).to.equal(amount); }); it('Should transferERC20', async function () { const amount = ethers.utils.parseEther('1'); - const receiverAddress = await user2.getAddress(); - let tx = await erc20.approve(sharedWallet.address, amount); + const receiverAddress = await user.getAddress(); + let tx = await erc20.approve(sharedWalletProxy.address, amount); await tx.wait(); - tx = await sharedWallet.transferERC20(erc20.address, receiverAddress, amount); + tx = await sharedWalletProxy.transferERC20(erc20.address, receiverAddress, amount); await tx.wait(); expect(await erc20.balanceOf(receiverAddress)).to.equal(amount); @@ -60,43 +59,49 @@ describe('SharedWallet TEST', function () { it('Should approveERC721', async function () { const tokenId = 1; - const receiverAddress = await user2.getAddress(); + const receiverAddress = await user.getAddress(); let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); await tx.wait(); console.log('ownerOf', await erc721.ownerOf(tokenId)); - tx = await sharedWallet.approveERC721(erc721.address, receiverAddress, tokenId); + tx = await sharedWalletProxy.approveERC721(erc721.address, receiverAddress, tokenId); await tx.wait(); expect(await erc721.getApproved(tokenId)).to.equal(receiverAddress); }); it('Should transferERC721', async function () { - const receiverAddress = await user2.getAddress(); + const receiverAddress = await user.getAddress(); let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); await tx.wait(); const tokenId = 1; - tx = await erc721.approve(sharedWallet.address, tokenId); + tx = await erc721.approve(sharedWalletProxy.address, tokenId); await tx.wait(); - tx = await sharedWallet.transferERC721(erc721.address, receiverAddress, tokenId); + tx = await sharedWalletProxy.transferERC721(erc721.address, receiverAddress, tokenId); await tx.wait(); expect(await erc721.ownerOf(tokenId)).to.equal(receiverAddress); }); it('Should grant a Manager Role', async function () { - const receiverAddress = await user2.getAddress(); - await sharedWallet.grantRole(MANAGER_ROLE, receiverAddress); + const receiverAddress = await user.getAddress(); + await sharedWalletProxy.grantRole(MANAGER_ROLE, receiverAddress); - expect(await sharedWallet.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(true); + expect(await sharedWalletProxy.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(true); }); it('Should revoke a Manager Role', async function () { - const receiverAddress = await user2.getAddress(); - await sharedWallet.revokeRole(MANAGER_ROLE, receiverAddress); + const receiverAddress = await user.getAddress(); + await sharedWalletProxy.revokeRole(MANAGER_ROLE, receiverAddress); - expect(await sharedWallet.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(false); + expect(await sharedWalletProxy.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(false); + }); + + it.only('Should upgrade the contract to Version 2', async function () { + const SharedWalletContractV2 = await ethers.getContractFactory('SharedWalletV2'); + sharedWalletProxy = await upgrades.upgradeProxy(sharedWalletProxy, SharedWalletContractV2); + expect(await sharedWalletProxy.isContractUpgraded()).to.equal(true); }); }); From 7e4c5634828eacb24198f474126fd14cba298004 Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Wed, 12 Oct 2022 20:20:29 +0200 Subject: [PATCH 6/9] added more tests --- .openzeppelin/unknown-31337.json | 4 +-- test/08-SharedWallet.test.ts | 53 ++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json index 3fc39de..332f3ab 100644 --- a/.openzeppelin/unknown-31337.json +++ b/.openzeppelin/unknown-31337.json @@ -148,8 +148,8 @@ } }, "a1c5cebe331372a4f5706386561899d7e5fd3e949f492327a4869bca85a43c36": { - "address": "0x15FC0878406CcF4d2963235A5B1EF68C67F17Ee5", - "txHash": "0xb4184fe932416b84e55bce996424e07aece1207b2a2362553fca0b5f42309345", + "address": "0x24E91C3a2822bDc4bc73512872ab07fD93c8101b", + "txHash": "0xb4e67678fc60f3f93b5abf831337a90e2c55ff8a79c6f3fe85a5a689d6baf34c", "layout": { "solcVersion": "0.8.6", "storage": [ diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts index 7d7c7c8..d04a6dd 100644 --- a/test/08-SharedWallet.test.ts +++ b/test/08-SharedWallet.test.ts @@ -7,13 +7,15 @@ import { MANAGER_ROLE } from './utils'; describe('SharedWallet TEST', function () { let owner, user: Signer, + user2: Signer, + user3: Signer, erc20: Contract, erc721: Contract, sharedWalletProxy: Contract, contractOwnerAddress: string; before(async function () { - [owner, user] = await ethers.getSigners(); + [owner, user, user2, user3] = await ethers.getSigners(); const MockERC20TokenContract = await ethers.getContractFactory('LimitedSupplyToken'); erc20 = await MockERC20TokenContract.deploy( @@ -57,6 +59,21 @@ describe('SharedWallet TEST', function () { expect(await erc20.balanceOf(receiverAddress)).to.equal(amount); }); + it('Should NOT transferERC20', async function () { + const amount = ethers.utils.parseEther('1'); + const receiverAddress = await user.getAddress(); + + expect( + sharedWalletProxy.connect(user3).transferERC20(erc20.address, receiverAddress, amount), + ).to.be.revertedWith('Caller is not a manager'); + + await sharedWalletProxy.grantRole(MANAGER_ROLE, await user2.getAddress()); + + expect( + sharedWalletProxy.connect(user2).transferERC20(erc20.address, receiverAddress, amount), + ).to.be.revertedWith('INSUFFICIENT BALANCE'); + }); + it('Should approveERC721', async function () { const tokenId = 1; const receiverAddress = await user.getAddress(); @@ -85,6 +102,20 @@ describe('SharedWallet TEST', function () { expect(await erc721.ownerOf(tokenId)).to.equal(receiverAddress); }); + it('Should NOT transferERC721', async function () { + const receiverAddress = await user.getAddress(); + + let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); + await tx.wait(); + const tokenId = 1; + + expect( + sharedWalletProxy.connect(user3).transferERC721(erc721.address, receiverAddress, tokenId), + ).to.be.revertedWith('Caller is not a manager'); + + expect(await erc721.ownerOf(tokenId)).to.equal(receiverAddress); + }); + it('Should grant a Manager Role', async function () { const receiverAddress = await user.getAddress(); await sharedWalletProxy.grantRole(MANAGER_ROLE, receiverAddress); @@ -92,6 +123,15 @@ describe('SharedWallet TEST', function () { expect(await sharedWalletProxy.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(true); }); + it('Should NOT grant a Manager Role', async function () { + const receiverAddress = await user.getAddress(); + await sharedWalletProxy.grantRole(MANAGER_ROLE, receiverAddress); + + expect(sharedWalletProxy.connect(user).grantRole(MANAGER_ROLE, receiverAddress)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + it('Should revoke a Manager Role', async function () { const receiverAddress = await user.getAddress(); await sharedWalletProxy.revokeRole(MANAGER_ROLE, receiverAddress); @@ -99,7 +139,16 @@ describe('SharedWallet TEST', function () { expect(await sharedWalletProxy.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(false); }); - it.only('Should upgrade the contract to Version 2', async function () { + it('Should NOT revoke a Manager Role', async function () { + const receiverAddress = await user.getAddress(); + await sharedWalletProxy.grantRole(MANAGER_ROLE, receiverAddress); + + expect(sharedWalletProxy.connect(user).revokeRole(MANAGER_ROLE, receiverAddress)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); + }); + + it('Should upgrade the contract to Version 2', async function () { const SharedWalletContractV2 = await ethers.getContractFactory('SharedWalletV2'); sharedWalletProxy = await upgrades.upgradeProxy(sharedWalletProxy, SharedWalletContractV2); expect(await sharedWalletProxy.isContractUpgraded()).to.equal(true); From c5651875e7ff435526a207626469563dcc2bb47e Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Thu, 13 Oct 2022 11:33:07 +0200 Subject: [PATCH 7/9] fixed tests --- .openzeppelin/unknown-31337.json | 28 ++++-- contracts/modules/Wallet/SharedWallet.sol | 9 +- test/08-SharedWallet.test.ts | 112 +++++++++------------- 3 files changed, 67 insertions(+), 82 deletions(-) diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json index 332f3ab..a7283c0 100644 --- a/.openzeppelin/unknown-31337.json +++ b/.openzeppelin/unknown-31337.json @@ -1,8 +1,8 @@ { "manifestVersion": "3.2", "admin": { - "address": "0xb63564A81D5d4004F4f22E9aB074cE25540B0C26", - "txHash": "0xb50d471597a4174b783d339ea368a8ed05dbd631d4a241ad95e9a9c22824d145" + "address": "0xEAB9a65eB0F098f822033192802B53EE159De5F0", + "txHash": "0x910db032b0f064cee37bb1700c2e6e8d78ac1bffc1c8fb77491431892f3ce1e9" }, "proxies": [ { @@ -12,14 +12,24 @@ }, { "address": "0x50aF0922d65D04D87d810048Dc640E2474eBfbd9", - "txHash": "0xeaf74320d4a412217e94605eea724ef15d7f146e6adcb24fd30ea22d9ba77dfa", + "txHash": "0x82ac7524e1bcb112454502f74ed59df2502e9f536ac8fa348b3f71d85663444e", + "kind": "transparent" + }, + { + "address": "0x15FC0878406CcF4d2963235A5B1EF68C67F17Ee5", + "txHash": "0x1a9a1cd2038eba3bfd476c4f6cb912aa127698f070520941be937925c512b00f", + "kind": "transparent" + }, + { + "address": "0x055cBfeD6df4AFE2452b18fd3D2592D1795592b4", + "txHash": "0x97e17a9c66d2b06a8c4217a176dfc0277cf5d510506e6a95fd9783d4e9e521c6", "kind": "transparent" } ], "impls": { - "1be117df27ae37206e8eb90713306e7623c7ea0f9a3c866624fa29c68a84f0da": { - "address": "0x055cBfeD6df4AFE2452b18fd3D2592D1795592b4", - "txHash": "0x493c96c515d349b4bf0bc45975165d677069f4fd07eea8ca6362493d13561604", + "a1c5cebe331372a4f5706386561899d7e5fd3e949f492327a4869bca85a43c36": { + "address": "0x24E91C3a2822bDc4bc73512872ab07fD93c8101b", + "txHash": "0x3a719927c38f2a4591e3780bb4c1aa9989b45c55f88745e1608a4f7685d9a7e9", "layout": { "solcVersion": "0.8.6", "storage": [ @@ -147,9 +157,9 @@ } } }, - "a1c5cebe331372a4f5706386561899d7e5fd3e949f492327a4869bca85a43c36": { - "address": "0x24E91C3a2822bDc4bc73512872ab07fD93c8101b", - "txHash": "0xb4e67678fc60f3f93b5abf831337a90e2c55ff8a79c6f3fe85a5a689d6baf34c", + "7c46d57ccc8bf95723fb4a7f082e3004be042211e7cee730d0f3823b266bd781": { + "address": "0x278Ff6d33826D906070eE938CDc9788003749e93", + "txHash": "0xc3f4e5a5fce191c49311cfb0d5ab0a927de7a02547c5a4b0c1b723a0fb342972", "layout": { "solcVersion": "0.8.6", "storage": [ diff --git a/contracts/modules/Wallet/SharedWallet.sol b/contracts/modules/Wallet/SharedWallet.sol index fde0b00..1e40db9 100644 --- a/contracts/modules/Wallet/SharedWallet.sol +++ b/contracts/modules/Wallet/SharedWallet.sol @@ -7,7 +7,6 @@ import '@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol'; import '@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol'; import '@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol'; import '@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol'; -import 'hardhat/console.sol'; contract SharedWallet is Initializable, AccessControlUpgradeable, OwnableUpgradeable { using SafeERC20Upgradeable for IERC20Upgradeable; @@ -21,7 +20,6 @@ contract SharedWallet is Initializable, AccessControlUpgradeable, OwnableUpgrade * @param _owner Address of the Owner contract. */ function initialize(address _owner) public initializer { - console.log('_owner', _owner); __Ownable_init(); transferOwnership(_owner); _grantRole(MANAGER_ROLE, _owner); @@ -32,9 +30,9 @@ contract SharedWallet is Initializable, AccessControlUpgradeable, OwnableUpgrade } function approveERC721(address _tokenAddress, address _address, uint256 _tokenId) external onlyManager { - IERC721Upgradeable token = IERC721Upgradeable(_tokenAddress); - console.log('ownerOf shared wallet', token.ownerOf(_tokenId)); - token.approve(_address, _tokenId); + IERC721Upgradeable erc721Token = IERC721Upgradeable(_tokenAddress); + require(erc721Token.ownerOf(_tokenId) == _msgSender(), 'Sender is not the owner of the token'); + erc721Token.approve(_address, _tokenId); } function transferERC20(address _tokenAddress, address _to, uint256 _amount) external onlyManager { @@ -45,6 +43,7 @@ contract SharedWallet is Initializable, AccessControlUpgradeable, OwnableUpgrade function transferERC721(address _tokenAddress, address _to, uint256 _tokenId) external onlyManager { IERC721Upgradeable erc721Token = IERC721Upgradeable(_tokenAddress); + require(erc721Token.ownerOf(_tokenId) == _msgSender(), 'Sender is not the owner of the token'); erc721Token.safeTransferFrom(_msgSender(), _to, _tokenId); } diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts index d04a6dd..ec05d0b 100644 --- a/test/08-SharedWallet.test.ts +++ b/test/08-SharedWallet.test.ts @@ -1,148 +1,124 @@ import { expect } from 'chai'; -import { Contract, Signer } from 'ethers'; -import { getAddress } from 'ethers/lib/utils'; +import { Console } from 'console'; +import { BigNumber, Contract, Signer } from 'ethers'; import { ethers, upgrades } from 'hardhat'; import { MANAGER_ROLE } from './utils'; describe('SharedWallet TEST', function () { - let owner, + let owner: any, user: Signer, user2: Signer, user3: Signer, erc20: Contract, erc721: Contract, sharedWalletProxy: Contract, - contractOwnerAddress: string; + contractOwnerAddress: string, + receiverAddress: string, + transferAmount: BigNumber, + tokenId: number; before(async function () { [owner, user, user2, user3] = await ethers.getSigners(); + console.log('owner', owner.address); + console.log('user', await user.getAddress()); + console.log('user2', await user2.getAddress()); + console.log('user3', await user3.getAddress()); + + contractOwnerAddress = await owner.getAddress(); + console.log('contractOwnerAddress', contractOwnerAddress); + receiverAddress = await user.getAddress(); + transferAmount = ethers.utils.parseEther('1'); + tokenId = 1; + + const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); + sharedWalletProxy = await upgrades.deployProxy(SharedWalletContract, [contractOwnerAddress]); + await sharedWalletProxy.deployed(); + console.log('SharedWallet DEPLOYED'); + const MockERC20TokenContract = await ethers.getContractFactory('LimitedSupplyToken'); erc20 = await MockERC20TokenContract.deploy( 'ExampleERC20', 'EX20', - await owner.getAddress(), + contractOwnerAddress, ethers.utils.parseEther('10'), ); await erc20.deployed(); console.log('MockERC20TokenContract DEPLOYED'); - contractOwnerAddress = getAddress(await owner.getAddress()); + const MockERC721Contract = await ethers.getContractFactory('NonFungibleToken'); erc721 = await MockERC721Contract.deploy('ExampleERC721', 'EX721', 'baseURI', contractOwnerAddress); await erc721.deployed(); console.log('MockERC721Contract DEPLOYED'); - const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); - sharedWalletProxy = await upgrades.deployProxy(SharedWalletContract, [contractOwnerAddress]); - await sharedWalletProxy.deployed(); - console.log('SharedWallet DEPLOYED'); + // set the proxycontract as operator + await erc721.setApprovalForAll(sharedWalletProxy.address, true); + + // mint a token + await erc721.mint(contractOwnerAddress, 'tokenURI'); + expect(await erc721.ownerOf(tokenId)).to.equal(contractOwnerAddress); }); it('Should approveERC20', async function () { - const amount = ethers.utils.parseEther('1'); - const receiverAddress = await user.getAddress(); - - const tx = await sharedWalletProxy.approveERC20(erc20.address, receiverAddress, amount); - await tx.wait(); - - expect(await erc20.allowance(sharedWalletProxy.address, receiverAddress)).to.equal(amount); + await sharedWalletProxy.approveERC20(erc20.address, receiverAddress, transferAmount); + expect(await erc20.allowance(sharedWalletProxy.address, receiverAddress)).to.equal(transferAmount); }); it('Should transferERC20', async function () { - const amount = ethers.utils.parseEther('1'); - const receiverAddress = await user.getAddress(); - let tx = await erc20.approve(sharedWalletProxy.address, amount); - await tx.wait(); - tx = await sharedWalletProxy.transferERC20(erc20.address, receiverAddress, amount); - await tx.wait(); - - expect(await erc20.balanceOf(receiverAddress)).to.equal(amount); + await erc20.approve(sharedWalletProxy.address, transferAmount); + await sharedWalletProxy.transferERC20(erc20.address, receiverAddress, transferAmount); + expect(await erc20.balanceOf(receiverAddress)).to.equal(transferAmount); }); it('Should NOT transferERC20', async function () { - const amount = ethers.utils.parseEther('1'); - const receiverAddress = await user.getAddress(); - expect( - sharedWalletProxy.connect(user3).transferERC20(erc20.address, receiverAddress, amount), + sharedWalletProxy.connect(user3).transferERC20(erc20.address, receiverAddress, transferAmount), ).to.be.revertedWith('Caller is not a manager'); await sharedWalletProxy.grantRole(MANAGER_ROLE, await user2.getAddress()); expect( - sharedWalletProxy.connect(user2).transferERC20(erc20.address, receiverAddress, amount), + sharedWalletProxy.connect(user2).transferERC20(erc20.address, receiverAddress, transferAmount), ).to.be.revertedWith('INSUFFICIENT BALANCE'); }); it('Should approveERC721', async function () { - const tokenId = 1; - const receiverAddress = await user.getAddress(); - - let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); - await tx.wait(); - - console.log('ownerOf', await erc721.ownerOf(tokenId)); - tx = await sharedWalletProxy.approveERC721(erc721.address, receiverAddress, tokenId); - await tx.wait(); - + await sharedWalletProxy.approveERC721(erc721.address, receiverAddress, tokenId); expect(await erc721.getApproved(tokenId)).to.equal(receiverAddress); }); - it('Should transferERC721', async function () { - const receiverAddress = await user.getAddress(); - - let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); - await tx.wait(); - const tokenId = 1; - tx = await erc721.approve(sharedWalletProxy.address, tokenId); - await tx.wait(); - tx = await sharedWalletProxy.transferERC721(erc721.address, receiverAddress, tokenId); - await tx.wait(); - - expect(await erc721.ownerOf(tokenId)).to.equal(receiverAddress); - }); - it('Should NOT transferERC721', async function () { - const receiverAddress = await user.getAddress(); - - let tx = await erc721.mint(contractOwnerAddress, 'tokenURI'); - await tx.wait(); - const tokenId = 1; - + await erc721.approve(sharedWalletProxy.address, tokenId); expect( sharedWalletProxy.connect(user3).transferERC721(erc721.address, receiverAddress, tokenId), ).to.be.revertedWith('Caller is not a manager'); + }); + it('Should transferERC721', async function () { + await erc721.approve(sharedWalletProxy.address, tokenId); + await sharedWalletProxy.transferERC721(erc721.address, receiverAddress, tokenId); expect(await erc721.ownerOf(tokenId)).to.equal(receiverAddress); }); it('Should grant a Manager Role', async function () { - const receiverAddress = await user.getAddress(); await sharedWalletProxy.grantRole(MANAGER_ROLE, receiverAddress); - expect(await sharedWalletProxy.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(true); }); it('Should NOT grant a Manager Role', async function () { - const receiverAddress = await user.getAddress(); await sharedWalletProxy.grantRole(MANAGER_ROLE, receiverAddress); - expect(sharedWalletProxy.connect(user).grantRole(MANAGER_ROLE, receiverAddress)).to.be.revertedWith( 'Ownable: caller is not the owner', ); }); it('Should revoke a Manager Role', async function () { - const receiverAddress = await user.getAddress(); await sharedWalletProxy.revokeRole(MANAGER_ROLE, receiverAddress); - expect(await sharedWalletProxy.hasRole(MANAGER_ROLE, receiverAddress)).to.equal(false); }); it('Should NOT revoke a Manager Role', async function () { - const receiverAddress = await user.getAddress(); await sharedWalletProxy.grantRole(MANAGER_ROLE, receiverAddress); - expect(sharedWalletProxy.connect(user).revokeRole(MANAGER_ROLE, receiverAddress)).to.be.revertedWith( 'Ownable: caller is not the owner', ); From 14cfdeaf87d6ed5f2cd3e840a7ddf757fbb34299 Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Thu, 13 Oct 2022 15:27:34 +0200 Subject: [PATCH 8/9] added new ContractName --- exports/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/exports/index.ts b/exports/index.ts index 9d82774..7017975 100644 --- a/exports/index.ts +++ b/exports/index.ts @@ -27,6 +27,9 @@ export const contractNames = [ 'ERC20SwapFacet', 'ERC721ProxyFacet', + // Wallet + 'SharedWallet', + // Deprecated facets 'TokenFactory', 'PoolRegistry', From e72c3b84ce49b0c188b1afb1c03d882c0412701d Mon Sep 17 00:00:00 2001 From: valeriagrazzini Date: Thu, 13 Oct 2022 16:00:50 +0200 Subject: [PATCH 9/9] updated version --- .openzeppelin/unknown-31337.json | 17 +++++++++++------ package-lock.json | 4 ++-- package.json | 2 +- test/08-SharedWallet.test.ts | 9 --------- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json index a7283c0..356d8a7 100644 --- a/.openzeppelin/unknown-31337.json +++ b/.openzeppelin/unknown-31337.json @@ -1,8 +1,8 @@ { "manifestVersion": "3.2", "admin": { - "address": "0xEAB9a65eB0F098f822033192802B53EE159De5F0", - "txHash": "0x910db032b0f064cee37bb1700c2e6e8d78ac1bffc1c8fb77491431892f3ce1e9" + "address": "0xcEA7ae904ABF6cFA09330fF01C56790cA916dEE5", + "txHash": "0xafdbaaf27843e38ab6528f6250a2a12477e98269dfdd9a74ab889a15c0e82210" }, "proxies": [ { @@ -24,12 +24,17 @@ "address": "0x055cBfeD6df4AFE2452b18fd3D2592D1795592b4", "txHash": "0x97e17a9c66d2b06a8c4217a176dfc0277cf5d510506e6a95fd9783d4e9e521c6", "kind": "transparent" + }, + { + "address": "0xEe3c47a790fA24672b42125EE010A3A5ca02d3D7", + "txHash": "0x8e4bb1794ff4542ea315ea4ce6d600b6d5f98cdf0e8967557ce2abb6eacc4769", + "kind": "transparent" } ], "impls": { "a1c5cebe331372a4f5706386561899d7e5fd3e949f492327a4869bca85a43c36": { - "address": "0x24E91C3a2822bDc4bc73512872ab07fD93c8101b", - "txHash": "0x3a719927c38f2a4591e3780bb4c1aa9989b45c55f88745e1608a4f7685d9a7e9", + "address": "0x40900cd70351aE8955D38A48823b89b9c0463AaA", + "txHash": "0xdddb3b04c2443e83041aa0900e5b3687119f933934eae5ceb0d222bf224dbddf", "layout": { "solcVersion": "0.8.6", "storage": [ @@ -158,8 +163,8 @@ } }, "7c46d57ccc8bf95723fb4a7f082e3004be042211e7cee730d0f3823b266bd781": { - "address": "0x278Ff6d33826D906070eE938CDc9788003749e93", - "txHash": "0xc3f4e5a5fce191c49311cfb0d5ab0a927de7a02547c5a4b0c1b723a0fb342972", + "address": "0xfCacA4fB3e2cB70671de40FF20E01248e356fBe3", + "txHash": "0x5c83585242a9d322319bffabb8b5383a431279717c82a3a31d711f28877a8e1e", "layout": { "solcVersion": "0.8.6", "storage": [ diff --git a/package-lock.json b/package-lock.json index 2a7af31..4045edd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@thxnetwork/artifacts", - "version": "4.0.6", + "version": "4.0.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@thxnetwork/artifacts", - "version": "4.0.6", + "version": "4.0.7", "license": "ISC", "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.1", diff --git a/package.json b/package.json index d115763..5b608d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thxnetwork/artifacts", - "version": "4.0.6", + "version": "4.0.7", "scripts": { "prettier": "prettier --write contracts/*.sol contracts/**/*.sol contracts/**/**/*.sol", "prettier-diff": "prettier --list-different contracts/*.sol contracts/**/*.sol contracts/**/**/*.sol", diff --git a/test/08-SharedWallet.test.ts b/test/08-SharedWallet.test.ts index ec05d0b..777f95f 100644 --- a/test/08-SharedWallet.test.ts +++ b/test/08-SharedWallet.test.ts @@ -20,13 +20,7 @@ describe('SharedWallet TEST', function () { before(async function () { [owner, user, user2, user3] = await ethers.getSigners(); - console.log('owner', owner.address); - console.log('user', await user.getAddress()); - console.log('user2', await user2.getAddress()); - console.log('user3', await user3.getAddress()); - contractOwnerAddress = await owner.getAddress(); - console.log('contractOwnerAddress', contractOwnerAddress); receiverAddress = await user.getAddress(); transferAmount = ethers.utils.parseEther('1'); tokenId = 1; @@ -34,7 +28,6 @@ describe('SharedWallet TEST', function () { const SharedWalletContract = await ethers.getContractFactory('SharedWallet'); sharedWalletProxy = await upgrades.deployProxy(SharedWalletContract, [contractOwnerAddress]); await sharedWalletProxy.deployed(); - console.log('SharedWallet DEPLOYED'); const MockERC20TokenContract = await ethers.getContractFactory('LimitedSupplyToken'); erc20 = await MockERC20TokenContract.deploy( @@ -44,12 +37,10 @@ describe('SharedWallet TEST', function () { ethers.utils.parseEther('10'), ); await erc20.deployed(); - console.log('MockERC20TokenContract DEPLOYED'); const MockERC721Contract = await ethers.getContractFactory('NonFungibleToken'); erc721 = await MockERC721Contract.deploy('ExampleERC721', 'EX721', 'baseURI', contractOwnerAddress); await erc721.deployed(); - console.log('MockERC721Contract DEPLOYED'); // set the proxycontract as operator await erc721.setApprovalForAll(sharedWalletProxy.address, true);