@@ -353,6 +353,7 @@ async function verifySingleContract(
353353 apiKey : string ,
354354 proxyOnly : boolean ,
355355 implOnly : boolean ,
356+ includePending : boolean ,
356357) : Promise < VerifyResult > {
357358 const addressBook = getAddressBookForType ( addressBookType , chainId )
358359
@@ -493,6 +494,47 @@ async function verifySingleContract(
493494 }
494495 }
495496
497+ // Verify the pending implementation (a new impl deployed but not yet live —
498+ // the proxy still points at `implementation` until governance executes the
499+ // upgrade). By default deploy:verify only covers the live implementation;
500+ // --include-pending also verifies `pendingImplementation` so the new code is
501+ // readable on the explorer before the upgrade is signed/executed. It's an
502+ // implementation, so --proxy-only skips it and only proxied entries have one.
503+ if ( includePending && ! proxyOnly && hasArtifact && entry . pendingImplementation ) {
504+ const pendingAddr = entry . pendingImplementation . address
505+ const pendingArgs = entry . pendingImplementation . deployment ?. argsData
506+
507+ const existingPendingUrl = await checkEtherscanVerified ( pendingAddr , apiKey , chainId )
508+ if ( existingPendingUrl ) {
509+ console . log ( ` ✓ Pending implementation already verified: ${ existingPendingUrl } ` )
510+ } else {
511+ const packageDir = getPackageDir ( metadata . artifact ! )
512+ const isHHv3 = isHardhatV3Package ( metadata . artifact ! )
513+ const artifact = loadArtifactFromSource ( metadata . artifact ! )
514+ const fullyQualifiedName = getFullyQualifiedContractName ( metadata . artifact ! )
515+
516+ console . log ( ` 📋 Verifying pending implementation at: ${ pendingAddr } ` )
517+ const pendingResult = await runVerify (
518+ packageDir ,
519+ networkName ,
520+ pendingAddr ,
521+ apiKey ,
522+ pendingArgs ,
523+ artifact ,
524+ isHHv3 ,
525+ fullyQualifiedName ,
526+ )
527+ if ( pendingResult . success ) {
528+ console . log (
529+ ` ✅ Pending implementation verification complete${ pendingResult . url ? `: ${ pendingResult . url } ` : '' } ` ,
530+ )
531+ } else {
532+ console . log ( ` ⚠️ Pending implementation verification failed (may already be verified)` )
533+ verificationFailed = true
534+ }
535+ }
536+ }
537+
496538 return { contract : contractName , addressBook : addressBookType , status : verificationFailed ? 'failed' : 'verified' }
497539}
498540
@@ -501,6 +543,7 @@ interface TaskArgs {
501543 addressBook : string
502544 proxyOnly : boolean
503545 implOnly : boolean
546+ includePending : boolean
504547}
505548
506549/**
@@ -518,9 +561,10 @@ interface TaskArgs {
518561 * npx hardhat deploy:verify --network arbitrumSepolia # verify all
519562 * npx hardhat deploy:verify --contract RewardsManager --network arbitrumSepolia # verify one
520563 * npx hardhat deploy:verify --impl-only --network arbitrumSepolia # implementations only
564+ * npx hardhat deploy:verify --include-pending --network arbitrumOne # also verify pending (pre-upgrade) impls
521565 */
522566const action : NewTaskActionFunction < TaskArgs > = async ( taskArgs , hre ) => {
523- const { contract, proxyOnly, implOnly } = taskArgs
567+ const { contract, proxyOnly, implOnly, includePending } = taskArgs
524568 const explicitAddressBook = taskArgs . addressBook || undefined
525569
526570 if ( proxyOnly && implOnly ) {
@@ -591,6 +635,7 @@ const action: NewTaskActionFunction<TaskArgs> = async (taskArgs, hre) => {
591635 apiKey ,
592636 proxyOnly ,
593637 implOnly ,
638+ includePending ,
594639 )
595640
596641 results . push ( result )
@@ -656,6 +701,12 @@ const verifyContractTask = task('deploy:verify', 'Verify deployed contracts on E
656701 type : ArgumentType . FLAG ,
657702 defaultValue : false ,
658703 } )
704+ . addOption ( {
705+ name : 'includePending' ,
706+ description : 'Also verify pendingImplementation addresses (new impls awaiting a governance upgrade)' ,
707+ type : ArgumentType . FLAG ,
708+ defaultValue : false ,
709+ } )
659710 . setAction ( async ( ) => ( { default : action } ) )
660711 . build ( )
661712
0 commit comments