@@ -34,6 +34,58 @@ import { isCustomFeeTokenAddress } from './utils/isCustomFeeTokenAddress';
3434import { WithTokenBridgeCreatorAddressOverride } from './types/createTokenBridgeTypes' ;
3535import { TransactionRequestGasOverrides } from './utils/gasOverrides' ;
3636import { getBlockExplorerUrl } from './utils/getBlockExplorerUrl' ;
37+ import { tokenBridgeCreatorABI } from './contracts/TokenBridgeCreator' ;
38+ import { getTokenBridgeCreatorAddress } from './utils' ;
39+ import { rollupABI } from './contracts/Rollup' ;
40+
41+ /**
42+ * If token bridge was already deployed, `createTokenBridge` will fail when waiting for retryables.
43+ * This function returns true if token bridge was deployed previously.
44+ *
45+ * @param {String } assertTokenBridgeDoesntExistParams.parentChainPublicClient - The parent chain Viem Public Client
46+ * @param {String } assertTokenBridgeDoesntExistParams.orbitChainPublicClient - The orbit chain Viem Public Client
47+ * @param {String= } assertTokenBridgeDoesntExistParams.tokenBridgeCreatorAddress - The TokenBridgeCreator address.
48+ * Default to getTokenBridgeCreatorAddress(parentChainPublicClient) if not provided
49+ * @param {String } assertTokenBridgeDoesntExistParams.rollupAddress - The address of the rollup on the parent chain
50+ *
51+ * @returns true if token bridge was already deployed
52+ */
53+ export async function isTokenBridgeDeployed <
54+ TParentChain extends Chain | undefined ,
55+ TOrbitChain extends Chain | undefined ,
56+ > ( {
57+ parentChainPublicClient,
58+ orbitChainPublicClient,
59+ tokenBridgeCreatorAddress,
60+ rollupAddress,
61+ } : {
62+ parentChainPublicClient : PublicClient < Transport , TParentChain > ;
63+ orbitChainPublicClient : PublicClient < Transport , TOrbitChain > ;
64+ tokenBridgeCreatorAddress ?: Address ;
65+ rollupAddress : Address ;
66+ } ) {
67+ const inbox = await parentChainPublicClient . readContract ( {
68+ address : rollupAddress ,
69+ abi : rollupABI ,
70+ functionName : 'inbox' ,
71+ } ) ;
72+
73+ const [ router ] = await parentChainPublicClient . readContract ( {
74+ address : tokenBridgeCreatorAddress ?? getTokenBridgeCreatorAddress ( parentChainPublicClient ) ,
75+ abi : tokenBridgeCreatorABI ,
76+ functionName : 'inboxToL2Deployment' ,
77+ args : [ inbox ] ,
78+ } ) ;
79+
80+ if ( router ) {
81+ const code = await orbitChainPublicClient . getBytecode ( { address : router } ) ;
82+ if ( code ) {
83+ return true ;
84+ }
85+ }
86+
87+ return false ;
88+ }
3789
3890export type CreateTokenBridgeParams <
3991 TParentChain extends Chain | undefined ,
@@ -171,6 +223,17 @@ export async function createTokenBridge<
171223} : CreateTokenBridgeParams < TParentChain , TOrbitChain > ) : Promise <
172224 CreateTokenBridgeResults < TParentChain , TOrbitChain >
173225> {
226+ const isTokenBridgeAlreadyDeployed = await isTokenBridgeDeployed ( {
227+ parentChainPublicClient,
228+ orbitChainPublicClient,
229+ tokenBridgeCreatorAddress : tokenBridgeCreatorAddressOverride ,
230+ rollupAddress,
231+ } ) ;
232+
233+ if ( isTokenBridgeAlreadyDeployed ) {
234+ throw new Error ( `Token bridge contracts for Rollup ${ rollupAddress } are already deployed` ) ;
235+ }
236+
174237 const isCustomFeeTokenBridge = isCustomFeeTokenAddress ( nativeTokenAddress ) ;
175238 if ( isCustomFeeTokenBridge ) {
176239 // set the custom fee token
0 commit comments