@@ -17,14 +17,93 @@ export interface FoundryArtefact {
1717 abi : Abi ;
1818 bytecode : {
1919 object : Hex ;
20+ linkReferences ?: Record < string , Record < string , Array < { start : number ; length : number } > > > ;
2021 } ;
2122}
2223
24+ // Cache deployed libraries to avoid redeploying
25+ const deployedLibraries = new Map < string , Address > ( ) ;
26+
27+ async function deployLibrary ( libraryName : string , libraryPath : string ) : Promise < Address > {
28+ // Check if already deployed
29+ const cacheKey = `${ libraryPath } :${ libraryName } ` ;
30+ if ( deployedLibraries . has ( cacheKey ) ) {
31+ return deployedLibraries . get ( cacheKey ) ! ;
32+ }
33+
34+ // Import and deploy the library
35+ const libraryArtifact = await import ( `../../contracts/out/${ libraryPath } /${ libraryName } .json` , {
36+ with : { type : 'json' }
37+ } ) ;
38+
39+ const hash = await client . deployContract ( {
40+ abi : libraryArtifact . default . abi ,
41+ account,
42+ bytecode : libraryArtifact . default . bytecode . object as Hex ,
43+ chain : client . chain
44+ } ) ;
45+
46+ const receipt = await client . waitForTransactionReceipt ( { hash } ) ;
47+ assert ( receipt . status === 'success' , 'Library deployment failed' ) ;
48+ assert ( ! ! receipt . contractAddress , 'Library address should not be empty' ) ;
49+
50+ deployedLibraries . set ( cacheKey , receipt . contractAddress ) ;
51+ return receipt . contractAddress ;
52+ }
53+
54+ function linkLibraries (
55+ bytecode : Hex ,
56+ linkReferences : Record < string , Record < string , Array < { start : number ; length : number } > > > ,
57+ libraryAddresses : Map < string , Address >
58+ ) : Hex {
59+ let linkedBytecode = bytecode ;
60+
61+ for ( const [ filePath , libraries ] of Object . entries ( linkReferences ) ) {
62+ for ( const [ libraryName , references ] of Object . entries ( libraries ) ) {
63+ const libraryAddress = libraryAddresses . get ( `${ filePath } :${ libraryName } ` ) ;
64+ assert ( ! ! libraryAddress , `Library ${ libraryName } not deployed` ) ;
65+
66+ const addressHex = libraryAddress . slice ( 2 ) . toLowerCase ( ) ;
67+
68+ // Replace all occurrences of the library placeholder
69+ for ( const ref of references ) {
70+ // Each reference has a start position (in bytes, so multiply by 2 for hex string)
71+ // Add 2 to skip '0x' prefix
72+ const startPos = ref . start * 2 + 2 ;
73+ const endPos = startPos + ref . length * 2 ;
74+
75+ linkedBytecode = ( linkedBytecode . slice ( 0 , startPos ) + addressHex + linkedBytecode . slice ( endPos ) ) as Hex ;
76+ }
77+ }
78+ }
79+
80+ return linkedBytecode ;
81+ }
82+
2383export async function deploySolidityProofVerifier ( artefact : FoundryArtefact ) : Promise < SolidityProofVerifier > {
84+ let bytecode = artefact . bytecode . object ;
85+
86+ // Deploy and link libraries if needed
87+ if ( artefact . bytecode . linkReferences && Object . keys ( artefact . bytecode . linkReferences ) . length > 0 ) {
88+ const libraryAddresses = new Map < string , Address > ( ) ;
89+
90+ for ( const [ filePath , libraries ] of Object . entries ( artefact . bytecode . linkReferences ) ) {
91+ for ( const libraryName of Object . keys ( libraries ) ) {
92+ const address = await deployLibrary (
93+ libraryName ,
94+ filePath . replace ( 'src/generated-verifier/' , '' ) . replace ( '.sol' , '.sol' )
95+ ) ;
96+ libraryAddresses . set ( `${ filePath } :${ libraryName } ` , address ) ;
97+ }
98+ }
99+
100+ bytecode = linkLibraries ( bytecode , artefact . bytecode . linkReferences , libraryAddresses ) ;
101+ }
102+
24103 const hash = await client . deployContract ( {
25104 abi : artefact . abi ,
26105 account,
27- bytecode : artefact . bytecode . object ,
106+ bytecode,
28107 chain : client . chain
29108 } ) ;
30109
0 commit comments