-
+
+
{
} as unknown as ChainInfo
it('should create a migration transaction for L1 chain', () => {
- const result = createUpdateMigration(mockChain)
+ const result = createUpdateMigration(mockChain, '1.3.0')
expect(result).toEqual({
operation: OperationType.DelegateCall,
@@ -336,8 +336,8 @@ describe('extractMigrationL2MasterCopyAddress', () => {
})
it('should create a migration transaction for L2 chain', () => {
- const l2Chain = { ...mockChain, l2: true }
- const result = createUpdateMigration(l2Chain)
+ const l2Chain = { ...mockChain, chainId: '137', l2: true }
+ const result = createUpdateMigration(l2Chain, '1.3.0+L2')
expect(result).toEqual({
operation: OperationType.DelegateCall,
@@ -348,7 +348,41 @@ describe('extractMigrationL2MasterCopyAddress', () => {
})
it('should throw an error if deployment is not found', () => {
- expect(() => createUpdateMigration(mockChainOld)).toThrow('Migration deployment not found')
+ expect(() => createUpdateMigration(mockChainOld, '1.1.1')).toThrow('Migration deployment not found')
+ })
+
+ it('should overwrite fallback handler if it is the default one', () => {
+ const result = createUpdateMigration(mockChain, '1.3.0', '0xf48f2B2d2a534e402487b3ee7C18c33Aec0Fe5e4') // 1.3.0 compatibility fallback handler
+
+ expect(result).toEqual({
+ operation: OperationType.DelegateCall,
+ data: '0xed007fc6',
+ to: '0x526643F69b81B008F46d95CD5ced5eC0edFFDaC6',
+ value: '0',
+ })
+ })
+
+ it('should overwrite L2 fallback handler if it is the default one', () => {
+ const l2Chain = { ...mockChain, chainId: '137', l2: true }
+ const result = createUpdateMigration(l2Chain, '1.3.0+L2', '0xf48f2B2d2a534e402487b3ee7C18c33Aec0Fe5e4') // 1.3.0 compatibility fallback handler
+
+ expect(result).toEqual({
+ operation: OperationType.DelegateCall,
+ data: '0x68cb3d94',
+ to: '0x526643F69b81B008F46d95CD5ced5eC0edFFDaC6',
+ value: '0',
+ })
+ })
+
+ it('should NOT overwrite a custom fallback handler', () => {
+ const result = createUpdateMigration(mockChain, '1.3.0', '0x526643F69b81B008F46d95CD5ced5eC0edFFDaC6')
+
+ expect(result).toEqual({
+ operation: OperationType.DelegateCall,
+ data: '0xf6682ab0',
+ to: '0x526643F69b81B008F46d95CD5ced5eC0edFFDaC6',
+ value: '0',
+ })
})
})
})
diff --git a/apps/web/src/utils/safe-migrations.ts b/apps/web/src/utils/safe-migrations.ts
index beffec8694..f9c1b6c7d6 100644
--- a/apps/web/src/utils/safe-migrations.ts
+++ b/apps/web/src/utils/safe-migrations.ts
@@ -1,9 +1,15 @@
import { Safe_to_l2_migration__factory, Safe_migration__factory } from '@/types/contracts'
+import { getCompatibilityFallbackHandlerDeployments } from '@safe-global/safe-deployments'
import { type ExtendedSafeInfo } from '@/store/safeInfoSlice'
-import { getSafeContractDeployment } from '@/services/contracts/deployments'
+import { getSafeContractDeployment, hasMatchingDeployment } from '@/services/contracts/deployments'
import { sameAddress } from './addresses'
import { getSafeToL2MigrationDeployment, getSafeMigrationDeployment } from '@safe-global/safe-deployments'
-import { type MetaTransactionData, OperationType, type SafeTransaction } from '@safe-global/safe-core-sdk-types'
+import {
+ type MetaTransactionData,
+ OperationType,
+ type SafeTransaction,
+ type SafeVersion,
+} from '@safe-global/safe-core-sdk-types'
import type { ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'
import { isValidMasterCopy } from '@/services/contracts/safeContracts'
import { isMultiSendCalldata } from './transaction-calldata'
@@ -95,9 +101,11 @@ export const prependSafeToL2Migration = (
return __unsafe_createMultiSendTx(newTxs)
}
-export const createUpdateMigration = (chain: ChainInfo): MetaTransactionData => {
- const interfce = Safe_migration__factory.createInterface()
-
+export const createUpdateMigration = (
+ chain: ChainInfo,
+ safeVersion: string,
+ fallbackHandler?: string,
+): MetaTransactionData => {
const deployment = getSafeMigrationDeployment({
version: chain.recommendedMasterCopyVersion || LATEST_SAFE_VERSION,
released: true,
@@ -108,11 +116,28 @@ export const createUpdateMigration = (chain: ChainInfo): MetaTransactionData =>
throw new Error('Migration deployment not found')
}
+ // Keep fallback handler if it's not a default one
+ const keepFallbackHandler =
+ !!fallbackHandler &&
+ !hasMatchingDeployment(getCompatibilityFallbackHandlerDeployments, fallbackHandler, chain.chainId, [
+ safeVersion as SafeVersion,
+ ])
+
+ const method = (
+ keepFallbackHandler
+ ? chain.l2
+ ? 'migrateL2Singleton'
+ : 'migrateSingleton'
+ : chain.l2
+ ? 'migrateL2WithFallbackHandler'
+ : 'migrateWithFallbackHandler'
+ ) as 'migrateSingleton' // apease typescript
+
+ const interfce = Safe_migration__factory.createInterface()
+
const tx: MetaTransactionData = {
- operation: OperationType.DelegateCall, // DELEGATE CALL REQUIRED
- data: chain.l2
- ? interfce.encodeFunctionData('migrateL2WithFallbackHandler')
- : interfce.encodeFunctionData('migrateWithFallbackHandler'),
+ operation: OperationType.DelegateCall, // delegate call required
+ data: interfce.encodeFunctionData(method),
to: deployment.defaultAddress,
value: '0',
}
diff --git a/yarn.lock b/yarn.lock
index 39c1caeac6..1a11c6e9ae 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1754,21 +1754,29 @@ __metadata:
languageName: node
linkType: hard
-"@cowprotocol/widget-lib@npm:^0.14.0":
- version: 0.14.0
- resolution: "@cowprotocol/widget-lib@npm:0.14.0"
+"@cowprotocol/iframe-transport@npm:^1.1.0":
+ version: 1.1.0
+ resolution: "@cowprotocol/iframe-transport@npm:1.1.0"
+ checksum: 10/20426255f0110b39801a051475a1352625a9c31f68f96947dfe162524213f10bc36e58d4ed58560a59ea893dcd47aebc5b4219ce97919dac7dabad07b96efbe3
+ languageName: node
+ linkType: hard
+
+"@cowprotocol/widget-lib@npm:^0.18.0":
+ version: 0.18.0
+ resolution: "@cowprotocol/widget-lib@npm:0.18.0"
dependencies:
- "@cowprotocol/events": "npm:^1.3.0"
- checksum: 10/8c745597c6ad7741ddd31957432c817a640ed73132320f3613062a0c3b4b48809202a5ee6cafb41e82afec1da5c1af87143ae781376b4611c5704305f3c2457e
+ "@cowprotocol/events": "npm:^1.5.0"
+ "@cowprotocol/iframe-transport": "npm:^1.1.0"
+ checksum: 10/fdc9dbeccfcdc3c65fc566289e2e59d42aa18f3ec501fbb6ccbbfdc5d4b24d3fff8011deaa7e323aa4a48fae886bd3b1d58d932129cc5cd237c9daa451d0c143
languageName: node
linkType: hard
-"@cowprotocol/widget-react@npm:^0.10.0":
- version: 0.10.0
- resolution: "@cowprotocol/widget-react@npm:0.10.0"
+"@cowprotocol/widget-react@npm:^0.13.0":
+ version: 0.13.0
+ resolution: "@cowprotocol/widget-react@npm:0.13.0"
dependencies:
- "@cowprotocol/widget-lib": "npm:^0.14.0"
- checksum: 10/8f683a6377e12fbacc672561102c1e7258519bcc751e5a2669b95f6fe01d5488184c8b3dee3d1aa33133c4783c03a65e104cd6107c9b51cf18033894e92d7c22
+ "@cowprotocol/widget-lib": "npm:^0.18.0"
+ checksum: 10/f2127f1dcdcbd3de102db670475b1256b5fd4fb9e4886cc1bf6ba1b4037df324ab76d5ead2a3302672971dda3b71ca284116e883e10a6af78c323b81eae3cc1f
languageName: node
linkType: hard
@@ -5651,10 +5659,10 @@ __metadata:
languageName: node
linkType: hard
-"@mui/core-downloads-tracker@npm:^6.2.1":
- version: 6.2.1
- resolution: "@mui/core-downloads-tracker@npm:6.2.1"
- checksum: 10/7b2b836f5a3c4eaffcd0b2c3e1863e168f0951f53ecbe6e5d2736686dfde18da1e21bcb24c237bde60d39f579773321c5b41ed9338cea3650cd3f5266bd489cd
+"@mui/core-downloads-tracker@npm:^6.3.0":
+ version: 6.3.0
+ resolution: "@mui/core-downloads-tracker@npm:6.3.0"
+ checksum: 10/cdfe2b2ba66c456587c7a285c0d2179ab5e42728e6a42d3921eb335c31aeeeda610ec728d96d797e4e82b298a229c20b6a74a7a8e6636d9f026f3d3240100e42
languageName: node
linkType: hard
@@ -5674,15 +5682,15 @@ __metadata:
languageName: node
linkType: hard
-"@mui/material@npm:^6.1.6":
- version: 6.2.1
- resolution: "@mui/material@npm:6.2.1"
+"@mui/material@npm:^6.3.0":
+ version: 6.3.0
+ resolution: "@mui/material@npm:6.3.0"
dependencies:
"@babel/runtime": "npm:^7.26.0"
- "@mui/core-downloads-tracker": "npm:^6.2.1"
- "@mui/system": "npm:^6.2.1"
+ "@mui/core-downloads-tracker": "npm:^6.3.0"
+ "@mui/system": "npm:^6.3.0"
"@mui/types": "npm:^7.2.20"
- "@mui/utils": "npm:^6.2.1"
+ "@mui/utils": "npm:^6.3.0"
"@popperjs/core": "npm:^2.11.8"
"@types/react-transition-group": "npm:^4.4.12"
clsx: "npm:^2.1.1"
@@ -5693,7 +5701,7 @@ __metadata:
peerDependencies:
"@emotion/react": ^11.5.0
"@emotion/styled": ^11.3.0
- "@mui/material-pigment-css": ^6.2.1
+ "@mui/material-pigment-css": ^6.3.0
"@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0
react: ^17.0.0 || ^18.0.0 || ^19.0.0
react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -5706,16 +5714,16 @@ __metadata:
optional: true
"@types/react":
optional: true
- checksum: 10/dcdfe23b893bb7798e61d335403e5e78fd94dba564787978eef37260963d7eeeee052b3953cacd8acb4b84df4b4eee4da5d6b22eb60c1d4d67dc896da680fb98
+ checksum: 10/e6db71b4d044c87e08d50fe7cea8c5667d0a10ea16e376aab83639029d7fbc350342b1c93f20d1f7b3b3c63f35eef09fe3dcada73f5c2f8f041887dc30d56ead
languageName: node
linkType: hard
-"@mui/private-theming@npm:^6.2.1":
- version: 6.2.1
- resolution: "@mui/private-theming@npm:6.2.1"
+"@mui/private-theming@npm:^6.3.0":
+ version: 6.3.0
+ resolution: "@mui/private-theming@npm:6.3.0"
dependencies:
"@babel/runtime": "npm:^7.26.0"
- "@mui/utils": "npm:^6.2.1"
+ "@mui/utils": "npm:^6.3.0"
prop-types: "npm:^15.8.1"
peerDependencies:
"@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0
@@ -5723,13 +5731,13 @@ __metadata:
peerDependenciesMeta:
"@types/react":
optional: true
- checksum: 10/554db0933120dc2630bca2c50ad986cba1f9a35fb7ce68dca09aaf2a430b6754d8e875addb47ccdf166ca8975d7140180535f1e836cc7a5531362080de1bd042
+ checksum: 10/61b19754f1f343866c47b9fa363482ddf79dab940620350fd707d863a74e18ec54540d3b2c19c94de7bdee78c75b00c0195ddd4f0019f2ee844e5e64c8c7a275
languageName: node
linkType: hard
-"@mui/styled-engine@npm:^6.2.1":
- version: 6.2.1
- resolution: "@mui/styled-engine@npm:6.2.1"
+"@mui/styled-engine@npm:^6.3.0":
+ version: 6.3.0
+ resolution: "@mui/styled-engine@npm:6.3.0"
dependencies:
"@babel/runtime": "npm:^7.26.0"
"@emotion/cache": "npm:^11.13.5"
@@ -5746,19 +5754,19 @@ __metadata:
optional: true
"@emotion/styled":
optional: true
- checksum: 10/d2b78317cc9ea14bf2dc3e2c28bb89b45db4fd9849932cc2732b96afe6efbcc9effce54f6faca5e5fd07a8041963f3ef31d746fcedab61fc1e3dce87e083bf15
+ checksum: 10/d36545fff9a50a508bc422ce0d20ecc5c24b7e3e9d64b7aa11117b16a382e4d4dd3aa2b127a94e150482999038e0437f631386b3727cb2ecfb00a75bf28877ac
languageName: node
linkType: hard
-"@mui/system@npm:^6.2.1":
- version: 6.2.1
- resolution: "@mui/system@npm:6.2.1"
+"@mui/system@npm:^6.3.0":
+ version: 6.3.0
+ resolution: "@mui/system@npm:6.3.0"
dependencies:
"@babel/runtime": "npm:^7.26.0"
- "@mui/private-theming": "npm:^6.2.1"
- "@mui/styled-engine": "npm:^6.2.1"
+ "@mui/private-theming": "npm:^6.3.0"
+ "@mui/styled-engine": "npm:^6.3.0"
"@mui/types": "npm:^7.2.20"
- "@mui/utils": "npm:^6.2.1"
+ "@mui/utils": "npm:^6.3.0"
clsx: "npm:^2.1.1"
csstype: "npm:^3.1.3"
prop-types: "npm:^15.8.1"
@@ -5774,7 +5782,7 @@ __metadata:
optional: true
"@types/react":
optional: true
- checksum: 10/17e2019fd0da1b4bf49e9e0f5347e7f2447d2908b3e0ad946e16e5a91c5c0bbeef58c2198f1c255e9f68a2ce1ce7eee34fa6fee285b373b9831857e5254b447a
+ checksum: 10/35e42c2182a745cb6caa476800580f536c5388064a837b0984faf4858b7537b0cc6dada11cef000100143903ea7130de306e1615f1b74cf5799c0a6ebb17e870
languageName: node
linkType: hard
@@ -5790,7 +5798,7 @@ __metadata:
languageName: node
linkType: hard
-"@mui/utils@npm:^5.16.6 || ^6.0.0, @mui/utils@npm:^6.2.1":
+"@mui/utils@npm:^5.16.6 || ^6.0.0":
version: 6.2.1
resolution: "@mui/utils@npm:6.2.1"
dependencies:
@@ -5810,6 +5818,26 @@ __metadata:
languageName: node
linkType: hard
+"@mui/utils@npm:^6.3.0":
+ version: 6.3.0
+ resolution: "@mui/utils@npm:6.3.0"
+ dependencies:
+ "@babel/runtime": "npm:^7.26.0"
+ "@mui/types": "npm:^7.2.20"
+ "@types/prop-types": "npm:^15.7.14"
+ clsx: "npm:^2.1.1"
+ prop-types: "npm:^15.8.1"
+ react-is: "npm:^19.0.0"
+ peerDependencies:
+ "@types/react": ^17.0.0 || ^18.0.0 || ^19.0.0
+ react: ^17.0.0 || ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ "@types/react":
+ optional: true
+ checksum: 10/09d78139405d761b92b0c722b27eb40b1a1993d1e146f6c1c5f505abd0c720ae135badb4f87b586fc8cefb0113c3ce7540e63fc54a6d19842fef14f9200ff864
+ languageName: node
+ linkType: hard
+
"@mui/x-date-pickers@npm:^7.22.1":
version: 7.23.2
resolution: "@mui/x-date-pickers@npm:7.23.2"
@@ -6771,6 +6799,23 @@ __metadata:
languageName: node
linkType: hard
+"@react-navigation/core@npm:^7.3.1":
+ version: 7.3.1
+ resolution: "@react-navigation/core@npm:7.3.1"
+ dependencies:
+ "@react-navigation/routers": "npm:^7.1.2"
+ escape-string-regexp: "npm:^4.0.0"
+ nanoid: "npm:3.3.8"
+ query-string: "npm:^7.1.3"
+ react-is: "npm:^18.2.0"
+ use-latest-callback: "npm:^0.2.1"
+ use-sync-external-store: "npm:^1.2.2"
+ peerDependencies:
+ react: ">= 18.2.0"
+ checksum: 10/94800b6b0a55cd9e7ffafbd508f434f65db4ce72d9a5f7d0420e6ca560d97c10ff95957a20a7f438fff28f1b96f37397cd433537058a076dc50e94ccd0c27975
+ languageName: node
+ linkType: hard
+
"@react-navigation/elements@npm:^2.2.4":
version: 2.2.4
resolution: "@react-navigation/elements@npm:2.2.4"
@@ -6837,6 +6882,22 @@ __metadata:
languageName: node
linkType: hard
+"@react-navigation/native@npm:^7.0.14":
+ version: 7.0.14
+ resolution: "@react-navigation/native@npm:7.0.14"
+ dependencies:
+ "@react-navigation/core": "npm:^7.3.1"
+ escape-string-regexp: "npm:^4.0.0"
+ fast-deep-equal: "npm:^3.1.3"
+ nanoid: "npm:3.3.8"
+ use-latest-callback: "npm:^0.2.1"
+ peerDependencies:
+ react: ">= 18.2.0"
+ react-native: "*"
+ checksum: 10/6a9987da929141c11bc711c2c44998e4ef74160cc6aba902cf268350b8c78a91f999d90a5be09390063d99d1ef38fb6b43008393a0d1854a96ef41a1aa59395f
+ languageName: node
+ linkType: hard
+
"@react-navigation/routers@npm:^7.1.1":
version: 7.1.1
resolution: "@react-navigation/routers@npm:7.1.1"
@@ -6846,6 +6907,15 @@ __metadata:
languageName: node
linkType: hard
+"@react-navigation/routers@npm:^7.1.2":
+ version: 7.1.2
+ resolution: "@react-navigation/routers@npm:7.1.2"
+ dependencies:
+ nanoid: "npm:3.3.8"
+ checksum: 10/8bc2f3907768e82898ea4b2daf83f301f40bdad50da2cb6d6b8382f0eb6da0804ec5beb88b183efdce2eb03f16d80b05e59a08e81e9809d99084605ad0f4dfb9
+ languageName: node
+ linkType: hard
+
"@redux-devtools/core@npm:^4.0.0":
version: 4.0.0
resolution: "@redux-devtools/core@npm:4.0.0"
@@ -7227,7 +7297,7 @@ __metadata:
"@react-native-menu/menu": "npm:^1.1.6"
"@react-native/babel-preset": "npm:^0.76.2"
"@react-navigation/material-top-tabs": "npm:^7.0.1"
- "@react-navigation/native": "npm:^7.0.0"
+ "@react-navigation/native": "npm:^7.0.14"
"@reduxjs/toolkit": "npm:^2.4.0"
"@rtk-query/codegen-openapi": "npm:^2.0.0"
"@safe-global/store": "workspace:^"
@@ -7247,7 +7317,7 @@ __metadata:
"@tamagui/animations-moti": "npm:^1.117.1"
"@tamagui/babel-plugin": "npm:^1.120.2"
"@tamagui/config": "npm:^1.117.1"
- "@tamagui/font-dm-sans": "npm:^1.117.1"
+ "@tamagui/font-dm-sans": "npm:^1.121.3"
"@tamagui/toast": "npm:^1.117.1"
"@testing-library/react-native": "npm:^12.7.2"
"@types/eslint__js": "npm:^8.42.3"
@@ -7449,7 +7519,7 @@ __metadata:
dependencies:
"@chromatic-com/storybook": "npm:^1.3.1"
"@cowprotocol/app-data": "npm:^2.4.0"
- "@cowprotocol/widget-react": "npm:^0.10.0"
+ "@cowprotocol/widget-react": "npm:^0.13.0"
"@ducanh2912/next-pwa": "npm:^10.2.9"
"@emotion/cache": "npm:^11.13.5"
"@emotion/react": "npm:^11.13.5"
@@ -7465,7 +7535,7 @@ __metadata:
"@mdx-js/loader": "npm:^3.0.1"
"@mdx-js/react": "npm:^3.0.1"
"@mui/icons-material": "npm:^6.1.6"
- "@mui/material": "npm:^6.1.6"
+ "@mui/material": "npm:^6.3.0"
"@mui/x-date-pickers": "npm:^7.22.1"
"@next/bundle-analyzer": "npm:^15.0.4"
"@next/mdx": "npm:^15.0.4"
@@ -10174,10 +10244,10 @@ __metadata:
languageName: node
linkType: hard
-"@tamagui/font-dm-sans@npm:^1.117.1":
- version: 1.119.0
- resolution: "@tamagui/font-dm-sans@npm:1.119.0"
- checksum: 10/2f7266688b96abbfa93097bb3c8cacbc240a0c38ac9f59c7843d340467c03a01cb10fe18c0471ba5016dc4955f4964262bdc51cf8cbb0c914a8330bf34fc21f9
+"@tamagui/font-dm-sans@npm:^1.121.3":
+ version: 1.121.3
+ resolution: "@tamagui/font-dm-sans@npm:1.121.3"
+ checksum: 10/90187a62c0cd668ef6bcd3810ae47b889a85dda316d023a3ada6cc959beae920ddf0f9a0a849b59d87eb7a5e7e065a1d305daeef44f7bb382c5909e16ff1ae9d
languageName: node
linkType: hard
@@ -25291,7 +25361,7 @@ __metadata:
languageName: node
linkType: hard
-"nanoid@npm:^3.3.1, nanoid@npm:^3.3.6, nanoid@npm:^3.3.7":
+"nanoid@npm:3.3.8, nanoid@npm:^3.3.1, nanoid@npm:^3.3.6, nanoid@npm:^3.3.7":
version: 3.3.8
resolution: "nanoid@npm:3.3.8"
bin: