diff --git a/contracts/proxy/dummyImpl.sol b/contracts/proxy/dummyImpl.sol new file mode 100644 index 0000000..4dc0e70 --- /dev/null +++ b/contracts/proxy/dummyImpl.sol @@ -0,0 +1,5 @@ +pragma solidity ^0.7.0; + +contract InstaEmptyImpl { + +} \ No newline at end of file diff --git a/contracts/proxy/proxyAdmin.sol b/contracts/proxy/proxyAdmin.sol new file mode 100644 index 0000000..ce06b57 --- /dev/null +++ b/contracts/proxy/proxyAdmin.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol"; + +interface IndexInterface { + function master() external view returns (address); +} + +/** + * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an + * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}. + */ +contract InstaMasterProxy { + + IndexInterface immutable public instaIndex; + + constructor(address _instaIndex) { + instaIndex = IndexInterface(_instaIndex); + } + + modifier isMaster() { + require(msg.sender == instaIndex.master(), "Implementations: not-master"); + _; + } + + /** + * @dev Returns the current implementation of `proxy`. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) { + // We need to manually run the static call since the getter cannot be flagged as view + // bytes4(keccak256("implementation()")) == 0x5c60da1b + (bool success, bytes memory returndata) = address(proxy).staticcall(hex"5c60da1b"); + require(success); + return abi.decode(returndata, (address)); + } + + /** + * @dev Returns the current admin of `proxy`. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) { + // We need to manually run the static call since the getter cannot be flagged as view + // bytes4(keccak256("admin()")) == 0xf851a440 + (bool success, bytes memory returndata) = address(proxy).staticcall(hex"f851a440"); + require(success); + return abi.decode(returndata, (address)); + } + + /** + * @dev Changes the admin of `proxy` to `newAdmin`. + * + * Requirements: + * + * - This contract must be the current admin of `proxy`. + */ + function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual isMaster { + proxy.changeAdmin(newAdmin); + } + + /** + * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual isMaster { + proxy.upgradeTo(implementation); + } + + /** + * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See + * {TransparentUpgradeableProxy-upgradeToAndCall}. + * + * Requirements: + * + * - This contract must be the admin of `proxy`. + */ + function upgradeAndCall(TransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable virtual isMaster { + proxy.upgradeToAndCall{value: msg.value}(implementation, data); + } +} \ No newline at end of file diff --git a/contracts/proxy/receivers.sol b/contracts/proxy/receivers.sol new file mode 100644 index 0000000..d03ae2d --- /dev/null +++ b/contracts/proxy/receivers.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol"; + +contract InstaAaveV2MigratorReceiver is TransparentUpgradeableProxy { + constructor(address _logic, address admin_, bytes memory _data) public TransparentUpgradeableProxy(_logic, admin_, _data) {} +} \ No newline at end of file diff --git a/contracts/proxy/senders.sol b/contracts/proxy/senders.sol new file mode 100644 index 0000000..c838291 --- /dev/null +++ b/contracts/proxy/senders.sol @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.7.0; + +import "@openzeppelin/contracts/proxy/TransparentUpgradeableProxy.sol"; + +contract InstaAaveV2MigratorSender is TransparentUpgradeableProxy { + constructor(address _logic, address admin_, bytes memory _data) public TransparentUpgradeableProxy(_logic, admin_, _data) {} +} \ No newline at end of file diff --git a/package.json b/package.json index 00cffbc..212d2b7 100644 --- a/package.json +++ b/package.json @@ -11,11 +11,16 @@ "license": "ISC", "devDependencies": { "@nomiclabs/hardhat-ethers": "^2.0.2", + "@nomiclabs/hardhat-etherscan": "^2.1.1", "@nomiclabs/hardhat-waffle": "^2.0.1", + "@nomiclabs/hardhat-web3": "^2.0.0", "chai": "^4.3.4", + "dotenv": "^7.0.0", "ethereum-waffle": "^3.3.0", "ethers": "^5.1.0", "hardhat": "^2.1.2", + "hardhat-deploy": "^0.7.0-beta.44", + "hardhat-deploy-ethers": "^0.3.0-beta.7", "solc": "0.7.0" }, "dependencies": { diff --git a/scripts/deploy.js b/scripts/deploy.js new file mode 100644 index 0000000..e973b96 --- /dev/null +++ b/scripts/deploy.js @@ -0,0 +1,84 @@ +const hre = require("hardhat"); +const { ethers } = hre; + +async function main() { + let instaIndex + if (hre.network.name === "mainnet") { + console.log( + "\n\n Deploying Contracts to mainnet. Hit ctrl + c to abort" + ); + instaIndex = "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723" + + const InstaEmptyImpl = await ethers.getContractFactory("InstaEmptyImpl"); + const instaEmptyImpl = await InstaEmptyImpl.deploy(); + await instaEmptyImpl.deployed(); + + console.log("InstaEmptyImpl deployed: ", instaEmptyImpl.address); + + + const InstaMasterProxy = await ethers.getContractFactory("InstaMasterProxy"); + const instaMasterProxy = await InstaMasterProxy.deploy(instaIndex); + await instaMasterProxy.deployed(); + + console.log("InstaMasterProxy deployed: ", instaMasterProxy.address); + + const InstaAaveV2MigratorSender = await ethers.getContractFactory("InstaAaveV2MigratorSender"); + const instaAaveV2MigratorSender = await InstaAaveV2MigratorSender.deploy(instaEmptyImpl.address, instaMasterProxy.address, "0x"); + await instaAaveV2MigratorSender.deployed(); + + console.log("InstaAaveV2MigratorSender deployed: ", instaAaveV2MigratorSender.address); + + await hre.run("verify:verify", { + address: instaEmptyImpl.address, + constructorArguments: [], + contract: "contracts/proxy/dummyImpl.sol:InstaEmptyImpl" + } + ) + + await hre.run("verify:verify", { + address: instaMasterProxy.address, + constructorArguments: [instaIndex], + } + ) + + await hre.run("verify:verify", { + address: instaAaveV2MigratorSender.address, + constructorArguments: [instaEmptyImpl.address, instaMasterProxy.address, "0x"], + contract: "contracts/proxy/senders.sol:InstaAaveV2MigratorSender" + } + ) + } else if (hre.network.name === "matic") { + console.log( + "\n\n Deploying Contracts to matic..." + ); + instaIndex = "0xA9B99766E6C676Cf1975c0D3166F96C0848fF5ad" + + + const InstaEmptyImpl = await ethers.getContractFactory("InstaEmptyImpl"); + const instaEmptyImpl = await InstaEmptyImpl.deploy(); + await instaEmptyImpl.deployed(); + + console.log("InstaEmptyImpl deployed: ", instaEmptyImpl.address); + + + const InstaMasterProxy = await ethers.getContractFactory("InstaMasterProxy"); + const instaMasterProxy = await InstaMasterProxy.deploy(instaIndex); + await instaMasterProxy.deployed(); + + console.log("InstaMasterProxy deployed: ", instaMasterProxy.address); + + const InstaAaveV2MigratorReceiver = await ethers.getContractFactory("InstaAaveV2MigratorReceiver"); + const instaAaveV2MigratorReceiver = await InstaAaveV2MigratorReceiver.deploy(instaEmptyImpl.address, instaMasterProxy.address, "0x"); + await instaAaveV2MigratorReceiver.deployed(); + + console.log("InstaAaveV2MigratorReceiver deployed: ", instaAaveV2MigratorReceiver.address); + console.log("Contracts deployed") + } +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); \ No newline at end of file diff --git a/scripts/flatten.sh b/scripts/flatten.sh new file mode 100755 index 0000000..ee8ccec --- /dev/null +++ b/scripts/flatten.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +baseContractPath='contracts' +function find() { + for file in "$1"/*; do + if [[ -d "$file" ]]; then + # echo "directory $file" + mkdir flatten/$file + find $file + elif [[ -f "$file" ]]; then + echo "Created [`basename "$file"`]" + npx hardhat flatten $file > flatten/$file + fi + done +} + +rm -rf flatten/$baseContractPath +mkdir flatten/$baseContractPath +find $baseContractPath \ No newline at end of file