From be592bc333a198b123dc2540739449771f18a7fe Mon Sep 17 00:00:00 2001 From: Andres Adjimann Date: Mon, 16 Dec 2024 13:55:59 -0300 Subject: [PATCH] feat: improve deployemnt scripts for nfg-collection --- .../02_deploy_nft_collection_beacon.ts | 75 ++++++------------- .../03_check_nft_collection_beacon.ts | 61 +++++++++++++++ .../100_deploy_nft_collection_mock.ts | 6 +- packages/deploy/utils/hardhatDeployUtils.ts | 22 ++++-- 4 files changed, 104 insertions(+), 60 deletions(-) create mode 100644 packages/deploy/deploy/28_nft_collection/03_check_nft_collection_beacon.ts diff --git a/packages/deploy/deploy/28_nft_collection/02_deploy_nft_collection_beacon.ts b/packages/deploy/deploy/28_nft_collection/02_deploy_nft_collection_beacon.ts index 60d1009982..b84909a4ba 100644 --- a/packages/deploy/deploy/28_nft_collection/02_deploy_nft_collection_beacon.ts +++ b/packages/deploy/deploy/28_nft_collection/02_deploy_nft_collection_beacon.ts @@ -8,9 +8,10 @@ import { } from '../../utils/hardhatDeployUtils'; import {getNamedAccounts} from 'hardhat'; -// hardhat-deploy don't support factory and beacons the way we use it +// hardhat-deploy don't support factory and beacons the way we use them const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {deployments, ethers} = hre; + const {nftCollectionAdmin} = await getNamedAccounts(); const beaconAlias = ethers.encodeBytes32String('nft-collection-v2'); const implementation = await deployments.get('NFTCollection_Implementation'); const beaconAddress = await deployments.read( @@ -19,59 +20,31 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { beaconAlias ); if (beaconAddress == ZeroAddress) { - await deployments.catchUnknownSigner( - deployBeacon(hre, beaconAlias, implementation) - ); - } else { - await performSanityChecks(hre, beaconAddress, implementation); + await deployments.catchUnknownSigner(async () => { + const receipt = await deployments.execute( + 'CollectionFactory', + {from: nftCollectionAdmin, log: true}, + 'deployBeacon', + implementation.address, + beaconAlias + ); + const eventArgs: {beaconAlias: string; beaconAddress: string} = + getEventArgsFromReceipt( + await ethers.getContract('CollectionFactory'), + receipt, + 'BeaconAdded' + ); + await saveDeployment( + deployments, + eventArgs.beaconAddress, + 'NFTCollection_Beacon', + 'UpgradeableBeacon', + receipt + ); + }); } }; -async function deployBeacon(hre, beaconAlias, implementation) { - const {deployments, ethers} = hre; - const {nftCollectionAdmin} = await getNamedAccounts(); - const receipt = await deployments.execute( - 'CollectionFactory', - {from: nftCollectionAdmin, log: true}, - 'deployBeacon', - implementation.address, - beaconAlias - ); - const eventArgs: {beaconAlias: string; beaconAddress: string} = - getEventArgsFromReceipt( - await ethers.getContract('CollectionFactory'), - receipt, - 'BeaconAdded' - ); - await saveDeployment( - deployments, - eventArgs.beaconAddress, - 'NFTCollection_Beacon', - 'UpgradeableBeacon', - receipt - ); -} - -async function performSanityChecks(hre, beaconAddress: string, implementation) { - const {deployments, ethers} = hre; - const beaconArtifact = await deployments.getArtifact('UpgradeableBeacon'); - const beacon = await ethers.getContractAt(beaconArtifact.abi, beaconAddress); - - const i = await beacon.implementation(); - if (i != implementation.address) { - throw new Error( - 'something went wrong: Beacon already deployed but has wrong implementation address, must call updateBeaconImplementation' - ); - } - const factory = await deployments.get('CollectionFactory'); - const o = await beacon.owner(); - if (o != factory.address) { - throw new Error( - 'something went wrong: Beacon already deployed but has wrong owner' - ); - } -} - export default func; func.tags = [ 'PolygonNFTCollection', diff --git a/packages/deploy/deploy/28_nft_collection/03_check_nft_collection_beacon.ts b/packages/deploy/deploy/28_nft_collection/03_check_nft_collection_beacon.ts new file mode 100644 index 0000000000..b1eb95ab8c --- /dev/null +++ b/packages/deploy/deploy/28_nft_collection/03_check_nft_collection_beacon.ts @@ -0,0 +1,61 @@ +import {ZeroAddress} from 'ethers'; +import {DeployFunction} from 'hardhat-deploy/types'; +import {HardhatRuntimeEnvironment} from 'hardhat/types'; +import {DEPLOY_TAGS} from '../../hardhat.config'; +import { + getEventArgsFromReceipt, + saveDeployment, +} from '../../utils/hardhatDeployUtils'; +import {getNamedAccounts} from 'hardhat'; + +// usually the deployments are done via defender proposals. +// This step lets us continue the deployment after proposal execution +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const {deployments, ethers} = hre; + const beaconAlias = ethers.encodeBytes32String('nft-collection-v2'); + const implementation = await deployments.get('NFTCollection_Implementation'); + const beaconAddress = await deployments.read( + 'CollectionFactory', + 'aliasToBeacon', + beaconAlias + ); + if (beaconAddress == ZeroAddress) { + throw new Error('Beacon deployment missing'); + } + const d = await deployments.getOrNull('NFTCollection_Beacon'); + if (!d) { + await saveDeployment( + deployments, + beaconAddress, + 'NFTCollection_Beacon', + 'UpgradeableBeacon' + ); + } + + const beaconArtifact = await deployments.getArtifact('UpgradeableBeacon'); + const beacon = await ethers.getContractAt(beaconArtifact.abi, beaconAddress); + const i = await beacon.implementation(); + if (i != implementation.address) { + throw new Error( + 'something went wrong: Beacon already deployed but has wrong implementation address, must call updateBeaconImplementation' + ); + } + const factory = await deployments.get('CollectionFactory'); + const o = await beacon.owner(); + if (o != factory.address) { + throw new Error( + 'something went wrong: Beacon already deployed but has wrong owner' + ); + } +}; + +export default func; +func.tags = [ + 'PolygonNFTCollection', + 'PolygonNFTCollection_Beacon', + 'PolygonNFTCollectionBeacon_check', + DEPLOY_TAGS.L2, + DEPLOY_TAGS.L2_PROD, + DEPLOY_TAGS.L2_TEST, +]; +func.dependencies = ['PolygonNFTCollectionBeacon_deploy']; diff --git a/packages/deploy/deploy/28_nft_collection/100_deploy_nft_collection_mock.ts b/packages/deploy/deploy/28_nft_collection/100_deploy_nft_collection_mock.ts index 26b5208a02..4356879a05 100644 --- a/packages/deploy/deploy/28_nft_collection/100_deploy_nft_collection_mock.ts +++ b/packages/deploy/deploy/28_nft_collection/100_deploy_nft_collection_mock.ts @@ -6,9 +6,9 @@ import { saveDeployment, } from '../../utils/hardhatDeployUtils'; -// Collections are created via backoffice, this script creates a collection -// for testing (TO BE USED ONLY ON TESTNETS) -// hardhat-deploy don't support factory and beacons the way we use it +// TO BE USED ONLY ON TESTNETS!!! +// Collections are created via backoffice, this script creates a testing collection +// hardhat-deploy don't support factory and beacons the way we use them const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const {deployments, getNamedAccounts, ethers} = hre; diff --git a/packages/deploy/utils/hardhatDeployUtils.ts b/packages/deploy/utils/hardhatDeployUtils.ts index de354e49a4..a07d2909b3 100644 --- a/packages/deploy/utils/hardhatDeployUtils.ts +++ b/packages/deploy/utils/hardhatDeployUtils.ts @@ -12,18 +12,28 @@ export async function saveDeployment( address: string, artifactName: string, contractName: string, - receipt: Receipt, + receipt?: Receipt, implementationAddress?: string ) { const extendedArtifact = await deployments.getExtendedArtifact(contractName); - console.log( - `saving "${artifactName}" (tx: ${receipt.transactionHash})...: deployed at ${address} with ${receipt.gasUsed} gas` - ); + if (receipt) { + console.log( + `saving "${artifactName}" (tx: ${receipt.transactionHash})...: deployed at ${address} with ${receipt.gasUsed} gas` + ); + } else { + console.log( + `saving "${artifactName}"...: deployed at ${address} without receipt` + ); + } await deployments.save(artifactName, { address, ...extendedArtifact, - receipt, - transactionHash: receipt.transactionHash, + ...(receipt + ? { + receipt, + transactionHash: receipt.transactionHash, + } + : {}), ...(implementationAddress ? {implementation: implementationAddress} : {}), } as DeploymentSubmission); }