diff --git a/extension/src/browser/Drawer/RolePermissionCheck.tsx b/extension/src/browser/Drawer/RolePermissionCheck.tsx index e91153b8..58abc991 100644 --- a/extension/src/browser/Drawer/RolePermissionCheck.tsx +++ b/extension/src/browser/Drawer/RolePermissionCheck.tsx @@ -60,6 +60,10 @@ const simulateRolesTransaction = async ( decodeRolesV2Error(e as JsonRpcError) if (decodedError) { + if (decodedError.name === 'ModuleTransactionFailed') { + return false + } + if (decodedError.name === 'ConditionViolation') { return RolesV2Status[decodedError.args.status] } diff --git a/extension/src/integrations/zodiac/useZodiacModules.ts b/extension/src/integrations/zodiac/useZodiacModules.ts index 2973dd83..e325c698 100644 --- a/extension/src/integrations/zodiac/useZodiacModules.ts +++ b/extension/src/integrations/zodiac/useZodiacModules.ts @@ -35,7 +35,6 @@ export const useZodiacModules = ( const [modules, setModules] = useState([]) const { chainId } = useRoute(connectionId) - useEffect(() => { setLoading(true) setError(false) @@ -57,8 +56,15 @@ export const useZodiacModules = ( async function fetchModules( safeOrModifierAddress: string, - chainId: ChainId + chainId: ChainId, + previous: Set = new Set() ): Promise { + if (previous.has(safeOrModifierAddress.toLowerCase())) { + // circuit breaker in case of circular module references + return [] + } + previous.add(safeOrModifierAddress.toLowerCase()) + const provider = getReadOnlyProvider(chainId) const mastercopyAddresses = ContractAddresses[chainId] || {} @@ -67,7 +73,6 @@ async function fetchModules( AvatarInterface, provider ) - const moduleAddresses = ( await contract.getModulesPaginated(ADDRESS_ONE, 100) )[0] as string[] @@ -115,7 +120,7 @@ async function fetchModules( if (MODIFIERS.includes(type)) { // recursively fetch modules from modifier try { - modules = await fetchModules(moduleAddress, chainId) + modules = await fetchModules(moduleAddress, chainId, previous) } catch (e) { console.error( `Could not fetch sub modules of ${type} modifier ${moduleAddress}`,