11// SPDX-FileCopyrightText: 2024-2025 IEXEC BLOCKCHAIN TECH <[email protected] > 22// SPDX-License-Identifier: Apache-2.0
33
4- import { ContractFactory , ZeroAddress } from 'ethers' ;
4+ import { ContractFactory , FunctionFragment , Interface , ZeroAddress } from 'ethers' ;
55import { ethers } from 'hardhat' ;
66import { FacetCut , FacetCutAction } from 'hardhat-deploy/dist/types' ;
7- import { DiamondCutFacet , DiamondLoupeFacet__factory } from '../typechain' ;
7+ import {
8+ DiamondCutFacet ,
9+ DiamondCutFacet__factory ,
10+ DiamondLoupeFacet__factory ,
11+ OwnershipFacet__factory ,
12+ IexecAccessorsABILegacyFacet__factory ,
13+ IexecCategoryManagerFacet__factory ,
14+ IexecConfigurationExtraFacet__factory ,
15+ IexecConfigurationFacet__factory ,
16+ IexecERC20Facet__factory ,
17+ IexecEscrowNativeFacet__factory ,
18+ IexecEscrowTokenFacet__factory ,
19+ IexecEscrowTokenSwapFacet__factory ,
20+ IexecOrderManagementFacet__factory ,
21+ IexecPoco1Facet__factory ,
22+ IexecPoco2Facet__factory ,
23+ IexecPocoAccessorsFacet__factory ,
24+ IexecPocoBoostAccessorsFacet__factory ,
25+ IexecPocoBoostFacet__factory ,
26+ IexecRelayFacet__factory ,
27+ } from '../typechain' ;
828import { getBaseNameFromContractFactory } from '../utils/deploy-tools' ;
929
1030const POCO_STORAGE_LOCATION = '0x5862653c6982c162832160cf30593645e8487b257e44d77cdd6b51eee2651b00' ;
@@ -29,6 +49,8 @@ export async function linkContractToProxy(
2949 contractAddress : string ,
3050 contractFactory : ContractFactory ,
3151) {
52+ const contractName = getBaseNameFromContractFactory ( contractFactory ) ;
53+ console . log ( `Linking ${ contractName } to proxy` ) ;
3254 // Fetch existing selectors from the proxy.
3355 const existingSelectors = await DiamondLoupeFacet__factory . connect (
3456 await proxy . getAddress ( ) ,
@@ -39,7 +61,7 @@ export async function linkContractToProxy(
3961 // Get the contract selectors from its ABI.
4062 const contractSelectors = getFunctionSelectors ( contractFactory ) ;
4163 // Exclude existing selectors to avoid the error `CannotAddFunctionToDiamondThatAlreadyExists`.
42- // This appears for `owner()` function.
64+ // This appears for `owner()` function for example .
4365 const selectors = contractSelectors . filter ( ( selector ) => ! existingSelectors . includes ( selector ) ) ;
4466 const facetCut : FacetCut = {
4567 facetAddress : contractAddress ,
@@ -50,7 +72,6 @@ export async function linkContractToProxy(
5072 . diamondCut ( [ facetCut ] , ZeroAddress , '0x' )
5173 . then ( ( tx ) => tx . wait ( ) )
5274 . catch ( ( err ) => {
53- const contractName = getBaseNameFromContractFactory ( contractFactory ) ;
5475 console . log ( `Failed to link ${ contractName } to proxy:` ) ;
5576 throw err ;
5677 } ) ;
@@ -87,3 +108,64 @@ export function getFunctionSelectors(contractFactory: ContractFactory): string[]
87108 } )
88109 ) ;
89110}
111+
112+ export function getAllLocalFacetFunctions ( ) : Map < string , string > {
113+ // TODO update this when new facets are added.
114+ // TODO read `contracts/facets` folder to avoid manual updates.
115+ const allInterfaces : Interface [ ] = [
116+ DiamondCutFacet__factory . createInterface ( ) ,
117+ DiamondLoupeFacet__factory . createInterface ( ) ,
118+ OwnershipFacet__factory . createInterface ( ) ,
119+ IexecAccessorsABILegacyFacet__factory . createInterface ( ) ,
120+ IexecCategoryManagerFacet__factory . createInterface ( ) ,
121+ IexecConfigurationExtraFacet__factory . createInterface ( ) ,
122+ IexecConfigurationFacet__factory . createInterface ( ) ,
123+ IexecERC20Facet__factory . createInterface ( ) ,
124+ IexecEscrowNativeFacet__factory . createInterface ( ) ,
125+ IexecEscrowTokenFacet__factory . createInterface ( ) ,
126+ IexecEscrowTokenSwapFacet__factory . createInterface ( ) ,
127+ IexecOrderManagementFacet__factory . createInterface ( ) ,
128+ IexecPoco1Facet__factory . createInterface ( ) ,
129+ IexecPoco2Facet__factory . createInterface ( ) ,
130+ IexecPocoAccessorsFacet__factory . createInterface ( ) ,
131+ IexecPocoBoostAccessorsFacet__factory . createInterface ( ) ,
132+ IexecPocoBoostFacet__factory . createInterface ( ) ,
133+ IexecRelayFacet__factory . createInterface ( ) ,
134+ ] ;
135+ // TODO update `getFunctionSelectors` and use it here to avoid duplication.
136+ const fragments : [ string , string ] [ ] = allInterfaces
137+ . flatMap ( ( iface ) => iface . fragments )
138+ . filter ( ( fragment ) => fragment . type === 'function' )
139+ . map ( ( fragment ) => fragment as FunctionFragment )
140+ . map ( ( fragment ) => [ fragment . selector , fragment . name ] as [ string , string ] )
141+ . concat ( [
142+ [ 'receive' , '0x00000000' ] , // fragment.type is 'fallback'
143+ [ 'fallback' , '0xffffffff' ] , // fragment.type is 'fallback'
144+ ] ) ;
145+ const selectorToName = new Map < string , string > ( fragments ) ;
146+ return selectorToName ;
147+ }
148+
149+ export async function printOnchainProxyFunctions ( diamondProxyAddress : string ) {
150+ const selectorToName = getAllLocalFacetFunctions ( ) ;
151+ const facetsOnchain = await DiamondLoupeFacet__factory . connect (
152+ diamondProxyAddress ,
153+ ethers . provider ,
154+ ) . facets ( ) ;
155+ let totalFunctions = 0 ;
156+ facetsOnchain . forEach ( ( facet ) => {
157+ totalFunctions += facet . functionSelectors . length ;
158+ } ) ;
159+ console . log (
160+ `Onchain diamond proxy has ${ facetsOnchain . length } facets and ${ totalFunctions } total functions:` ,
161+ ) ;
162+ let i = 0 ;
163+ for ( const facet of facetsOnchain ) {
164+ for ( const selector of facet . functionSelectors ) {
165+ // Fallback to the selector if the name is not found.
166+ const functionName = selectorToName . get ( selector ) ?? selector ;
167+ console . log ( `[${ i } ] ${ facet . facetAddress } ${ functionName } ` ) ;
168+ i ++ ;
169+ }
170+ }
171+ }
0 commit comments