From 6b7c98e9840e0f284a237c5530d67df704196f94 Mon Sep 17 00:00:00 2001 From: Fish Chen Date: Wed, 6 Mar 2024 11:48:32 +1100 Subject: [PATCH 1/5] added override input for estimateGas --- scripts/utils/helper.ts | 81 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 7 deletions(-) diff --git a/scripts/utils/helper.ts b/scripts/utils/helper.ts index d2d8ed42..cdc9fbda 100644 --- a/scripts/utils/helper.ts +++ b/scripts/utils/helper.ts @@ -3,6 +3,9 @@ import { Deferrable } from 'ethers/lib/utils'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { TransactionRequest } from "@ethersproject/abstract-provider"; import * as child from 'child_process'; +import { BigNumber, Overrides } from 'ethers'; + +const gasPricePctDiffAlert = 20; // Set threshold to alert when attempting to under/overpay against the current gas price median by X% (e.g. 20 = 20%) export const checkCodeVersion = async () => { const localLatestCommit = child.execSync('git rev-parse HEAD').toString().trim(); @@ -19,15 +22,79 @@ export const checkCodeVersion = async () => { return true; } -export const estimateGas = async (hre: HardhatRuntimeEnvironment, tx: Deferrable) => { +export const estimateGas = async ( + hre: HardhatRuntimeEnvironment, + tx: Deferrable, + overrides?: Overrides, +) => { + const overrideGasLimit = overrides?.gasLimit as BigNumber; + const overrideGasPrice = overrides?.gasPrice as BigNumber; const estimatedGasUnit = await hre.ethers.provider.estimateGas(tx); const estimatedGasPrice = await hre.ethers.provider.getGasPrice(); - const estimatedGas = estimatedGasUnit.mul(estimatedGasPrice); - console.log('Estimated gas unit: ', estimatedGasUnit.toString()); - console.log('Estimated gas price (GWei): ', estimatedGasPrice.div(1000000000).toString()); - console.log(`Estimated gas (${getTokenName(hre)}): `, hre.ethers.utils.formatEther(estimatedGas)); - return estimatedGas; -} + const estimatedGasCost = estimatedGasUnit.mul( + overrideGasPrice ?? estimatedGasPrice, + ); + if (overrideGasLimit && overrideGasLimit < estimatedGasUnit) { + const diffPct = + (estimatedGasUnit.toNumber() / overrideGasLimit.toNumber() - 1) * 100; + console.log( + '\x1b[31m[WARNING]\x1b[0m Estimated gas units required exceeds the limit set:', + `\x1b[33m${estimatedGasUnit.toNumber().toLocaleString()}\x1b[0m`, + `(${ + diffPct > 0 ? '+' + diffPct.toFixed(2) : diffPct.toFixed(2) + }% to the --gaslimit \x1b[33m${overrideGasLimit + .toNumber() + .toLocaleString()}\x1b[0m)`, + ); + if ( + !(await confirm({ + message: 'There is higher probability of failure. Continue?', + })) + ) + return null; + } else + console.log( + 'Estimated gas unit:', + `\x1b[33m${estimatedGasUnit.toNumber().toLocaleString()}\x1b[0m`, + ); + + const estimatedGasPriceFormat = estimatedGasPrice.div(1e9).toNumber(); + const overrideGasPriceFormat = overrideGasPrice + ? overrideGasPrice.div(1e9).toNumber() + : null; + if ( + overrideGasPriceFormat && + overrideGasPriceFormat !== estimatedGasPriceFormat + ) { + const diffPct = + (overrideGasPriceFormat / estimatedGasPriceFormat - 1) * 100; + console.log( + '\x1b[31m[WARNING]\x1b[0m Override gas price set (GWEI):', + overrideGasPriceFormat, + `(${ + diffPct > 0 ? '+' + diffPct.toFixed(2) : diffPct.toFixed(2) + }% to estimated gas price`, + estimatedGasPriceFormat, + `)`, + ); + if (Math.abs(diffPct) > gasPricePctDiffAlert) { + const aboveOrBelow = diffPct > 0 ? 'ABOVE' : 'BELOW'; + if ( + !(await confirm({ + message: `You are attempting to pay more than ${gasPricePctDiffAlert}% ${aboveOrBelow} estimated gas price. Continue?`, + })) + ) + return null; + } + } else console.log('Estimated gas price (GWEI):', estimatedGasPriceFormat); + + console.log( + `Estimated gas cost (${getTokenName(hre)}):`, + `\x1b[33m${hre.ethers.utils.formatEther(estimatedGasCost)}\x1b[0m`, + ); + + return estimatedGasCost; +}; const getTokenName = (hre: HardhatRuntimeEnvironment) => { switch(hre.network.name) { From d73ee3d5fbaea8d5b568988d20663942ff2768b4 Mon Sep 17 00:00:00 2001 From: Fish Chen Date: Wed, 6 Mar 2024 11:51:27 +1100 Subject: [PATCH 2/5] added gaspricegwei and gaslimit override for deploy --- hardhat.config.ts | 2 ++ scripts/deploy.ts | 26 ++++++++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 6557dc20..393acb44 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -159,6 +159,8 @@ task('deploy', 'Deploy ERC721M') .addOptionalParam('useerc2198', 'whether or not to use ERC2198', true, types.boolean) .addOptionalParam('erc2198royaltyreceiver', 'erc2198 royalty receiver address') .addOptionalParam('erc2198royaltyfeenumerator', 'erc2198 royalty fee numerator') + .addOptionalParam('gaspricegwei', 'Set gas price in Gwei') + .addOptionalParam('gaslimit', 'Set maximum gas units to spend on transaction') .setAction(deploy); task('setBaseURI', 'Set the base uri') diff --git a/scripts/deploy.ts b/scripts/deploy.ts index 7646799a..f7641e78 100644 --- a/scripts/deploy.ts +++ b/scripts/deploy.ts @@ -8,6 +8,7 @@ import { confirm } from '@inquirer/prompts'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { ContractDetails } from './common/constants'; import { checkCodeVersion, estimateGas } from './utils/helper'; +import { Overrides } from 'ethers'; export interface IDeployParams { name: string; @@ -25,8 +26,10 @@ export interface IDeployParams { mintcurrency?: string; useerc721c?: boolean; useerc2198?: boolean; - erc2198royaltyreceiver?: string, - erc2198royaltyfeenumerator?: number, + erc2198royaltyreceiver?: string; + erc2198royaltyfeenumerator?: number; + gaspricegwei?: number; + gaslimit?: number; } export const deploy = async ( @@ -71,6 +74,14 @@ export const deploy = async ( maxsupply = hre.ethers.BigNumber.from('999999999'); } + const overrides: Overrides = {}; + if (args.gaspricegwei) { + overrides.gasPrice = hre.ethers.BigNumber.from(args.gaspricegwei * 1e9); + } + if (args.gaslimit) { + overrides.gasLimit = hre.ethers.BigNumber.from(args.gaslimit); + } + const contractFactory = await hre.ethers.getContractFactory(contractName); const params = [ @@ -100,11 +111,18 @@ export const deploy = async ( JSON.stringify(args, null, 2), ); - await estimateGas(hre, contractFactory.getDeployTransaction(...params)); + if ( + !(await estimateGas( + hre, + contractFactory.getDeployTransaction(...params), + overrides, + )) + ) + return; if (!(await confirm({ message: 'Continue to deploy?' }))) return; - const contract = await contractFactory.deploy(...params); + const contract = await contractFactory.deploy(...params, overrides); console.log('Deploying contract... '); console.log('tx:', contract.deployTransaction.hash); From 48764f10b18a9a4226d669c6815f2bf47107be47 Mon Sep 17 00:00:00 2001 From: Fish Chen Date: Wed, 6 Mar 2024 17:30:23 +1100 Subject: [PATCH 3/5] added gaslimit param to setStages --- hardhat.config.ts | 1 + scripts/setStages.ts | 14 +++++++++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 393acb44..ebda208e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -117,6 +117,7 @@ task('setStages', 'Set stages for ERC721M') .addParam('contract', 'contract address') .addParam('stages', 'stages json file') .addOptionalParam('gaspricegwei', 'Set gas price in Gwei') + .addOptionalParam('gaslimit', 'Set maximum gas units to spend on transaction', 500000, types.int) .setAction(setStages); task('setMintable', 'Set mintable state for ERC721M') diff --git a/scripts/setStages.ts b/scripts/setStages.ts index e1c2fb9b..cd92b9b0 100644 --- a/scripts/setStages.ts +++ b/scripts/setStages.ts @@ -4,11 +4,13 @@ import { MerkleTree } from 'merkletreejs'; import fs from 'fs'; import { ContractDetails } from './common/constants'; import { estimateGas } from './utils/helper'; +import { Overrides } from 'ethers'; export interface ISetStagesParams { stages: string; contract: string; gaspricegwei?: number; + gaslimit?: number; } interface StageConfig { @@ -29,13 +31,15 @@ export const setStages = async ( fs.readFileSync(args.stages, 'utf-8'), ) as StageConfig[]; - const overrides: any = { gasLimit: 500_000 }; - const ERC721M = await ethers.getContractFactory(ContractDetails.ERC721M.name); const contract = ERC721M.attach(args.contract); + const overrides: Overrides = {}; if (args.gaspricegwei) { - overrides.gasPrice = args.gaspricegwei * 1e9; + overrides.gasPrice = ethers.BigNumber.from(args.gaspricegwei * 1e9); + } + if (args.gaslimit) { + overrides.gasLimit = ethers.BigNumber.from(args.gaslimit); } const merkleRoots = await Promise.all( stagesConfig.map((stage) => { @@ -85,8 +89,8 @@ export const setStages = async ( ), ); - const tx = await contract.populateTransaction.setStages(stages, overrides); - estimateGas(hre, tx); + const tx = await contract.populateTransaction.setStages(stages); + if (!(await estimateGas(hre, tx, overrides))) return; if (!await confirm({ message: 'Continue to set stages?' })) return; From 2c34ebc94d9c530b3b4271c56c9cc7d693a6ed06 Mon Sep 17 00:00:00 2001 From: Fish Chen Date: Thu, 7 Mar 2024 09:43:24 +1100 Subject: [PATCH 4/5] added gaspricegwei and gaslimit override for ownerMint --- hardhat.config.ts | 2 ++ scripts/ownerMint.ts | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index ebda208e..0df44357 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -185,6 +185,8 @@ task('ownerMint', 'Mint token(s) as owner') .addParam('contract', 'contract address') .addParam('qty', 'quantity to mint', '1') .addOptionalParam('to', 'recipient address') + .addOptionalParam('gaspricegwei', 'Set gas price in Gwei') + .addOptionalParam('gaslimit', 'Set maximum gas units to spend on transaction') .setAction(ownerMint); task('setGlobalWalletLimit', 'Set the global wallet limit') diff --git a/scripts/ownerMint.ts b/scripts/ownerMint.ts index d53a1070..34d30288 100644 --- a/scripts/ownerMint.ts +++ b/scripts/ownerMint.ts @@ -2,11 +2,14 @@ import { confirm } from '@inquirer/prompts'; import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { ContractDetails } from './common/constants'; import { estimateGas } from './utils/helper'; +import { Overrides } from 'ethers'; export interface IOwnerMintParams { contract: string; to?: string; qty?: string; + gaspricegwei?: number; + gaslimit?: number; } export const ownerMint = async ( @@ -19,13 +22,20 @@ export const ownerMint = async ( const contract = ERC721M.attach(args.contract); const qty = ethers.BigNumber.from(args.qty ?? 1); const to = args.to ?? (await contract.signer.getAddress()); + const overrides: Overrides = {}; + if (args.gaspricegwei) { + overrides.gasPrice = ethers.BigNumber.from(args.gaspricegwei * 1e9); + } + if (args.gaslimit) { + overrides.gasLimit = ethers.BigNumber.from(args.gaslimit); + } const tx = await contract.populateTransaction.ownerMint(qty, to); - await estimateGas(hre, tx); + if (!(await estimateGas(hre, tx, overrides))) return; console.log(`Going to mint ${qty.toNumber()} token(s) to ${to}`); if (!await confirm({ message: 'Continue?' })) return; - const submittedTx = await contract.ownerMint(qty, to); + const submittedTx = await contract.ownerMint(qty, to, overrides); console.log(`Submitted tx ${submittedTx.hash}`); await submittedTx.wait(); From ced1c9edb62d915f165aff4184847e7656174661 Mon Sep 17 00:00:00 2001 From: Fish Chen Date: Thu, 7 Mar 2024 09:51:56 +1100 Subject: [PATCH 5/5] added gaslimit param to setBaseURI --- hardhat.config.ts | 1 + scripts/setBaseURI.ts | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/hardhat.config.ts b/hardhat.config.ts index 0df44357..67561aa3 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -168,6 +168,7 @@ task('setBaseURI', 'Set the base uri') .addParam('uri', 'uri') .addParam('contract', 'contract address') .addOptionalParam('gaspricegwei', 'Set gas price in Gwei') + .addOptionalParam('gaslimit', 'Set maximum gas units to spend on transaction', 500000, types.int) .setAction(setBaseURI); task('setCrossmintAddress', 'Set crossmint address') diff --git a/scripts/setBaseURI.ts b/scripts/setBaseURI.ts index 0d2840fd..d4cb87db 100644 --- a/scripts/setBaseURI.ts +++ b/scripts/setBaseURI.ts @@ -1,10 +1,13 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types'; import { ContractDetails } from './common/constants'; +import { Overrides } from 'ethers'; +import { estimateGas } from './utils/helper'; export interface ISetBaseURIParams { uri: string; contract: string; gaspricegwei?: number; + gaslimit?: number; } export const setBaseURI = async ( @@ -12,18 +15,22 @@ export const setBaseURI = async ( hre: HardhatRuntimeEnvironment, ) => { const { ethers } = hre; - const overrides: any = {gasLimit: 500_000}; - + const overrides: Overrides = {}; if (args.gaspricegwei) { - overrides.gasPrice = args.gaspricegwei * 1e9; + overrides.gasPrice = ethers.BigNumber.from(args.gaspricegwei * 1e9); + } + if (args.gaslimit) { + overrides.gasLimit = ethers.BigNumber.from(args.gaslimit); } const ERC721M = await ethers.getContractFactory(ContractDetails.ERC721M.name); const contract = ERC721M.attach(args.contract); - const tx = await contract.setBaseURI(args.uri, overrides); + const tx = await contract.populateTransaction.setBaseURI(args.uri); + if (!(await estimateGas(hre, tx, overrides))) return; + const submittedTx = await contract.setBaseURI(args.uri, overrides); - console.log(`Submitted tx ${tx.hash}`); + console.log(`Submitted tx ${submittedTx.hash}`); - await tx.wait(); + await submittedTx.wait(); - console.log('Set baseURI:', tx.hash); + console.log('Set baseURI:', submittedTx.hash); };