Skip to content

Commit

Permalink
fix: handle nullable SafeInfo['version'] (#1340)
Browse files Browse the repository at this point in the history
* fix: handle nullable `SafeInfo['version']

* fix: install + fix types w/ new package

* fix: remove unnecessary optional chaining

* fix: add fallback version text

* fix: don't show link for unsupported contract
  • Loading branch information
iamacook authored Dec 13, 2022
1 parent 9b9d1a4 commit a7f8712
Show file tree
Hide file tree
Showing 10 changed files with 45 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"@reduxjs/toolkit": "^1.8.2",
"@safe-global/safe-core-sdk": "^3.2.0",
"@safe-global/safe-ethers-lib": "^1.7.0",
"@safe-global/safe-gateway-typescript-sdk": "^3.5.3",
"@safe-global/safe-gateway-typescript-sdk": "^3.5.4",
"@sentry/react": "^7.8.1",
"@sentry/tracing": "^7.8.1",
"@truffle/hdwallet-provider": "^2.0.14",
Expand Down
14 changes: 10 additions & 4 deletions src/components/settings/ContractVersion/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,16 @@ export const ContractVersion = ({ isGranted }: { isGranted: boolean }) => {
<Typography variant="h4" fontWeight={700} marginBottom={1}>
Contract version
</Typography>
<ExternalLink href={safeMasterCopy?.deployerRepoUrl}>
{safe.version}
{getSafeVersionUpdate()}
</ExternalLink>
{safe.version ? (
<ExternalLink href={safeMasterCopy?.deployerRepoUrl}>
{safe.version}
{getSafeVersionUpdate()}
</ExternalLink>
) : (
<Typography variant="body1" fontWeight={400}>
Unsupported contract
</Typography>
)}

{showUpdateDialog && isGranted && <UpdateSafeDialog />}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/settings/TransactionGuards/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const GUARD_SUPPORTED_SAFE_VERSION = '1.3.0'
const TransactionGuards = () => {
const { safe, safeLoaded } = useSafeInfo()

const isVersionWithGuards = safeLoaded && gte(safe.version, GUARD_SUPPORTED_SAFE_VERSION)
const isVersionWithGuards = safeLoaded && safe.version && gte(safe.version, GUARD_SUPPORTED_SAFE_VERSION)

if (!isVersionWithGuards) {
return null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ const ReviewBatchExecute = ({ data, onSubmit }: { data: BatchExecuteData; onSubm
}, [data.txs, chain?.chainId])

const multiSendContract = useMemo(() => {
if (!chain?.chainId) return
if (!chain?.chainId || !safe.version) return
return getMultiSendCallOnlyContractInstance(chain.chainId, safe.version)
}, [chain?.chainId, safe.version])

const multiSendTxs = useMemo(() => {
if (!txsWithDetails || !chain) return
if (!txsWithDetails || !chain || !safe.version) return
return getMultiSendTxs(txsWithDetails, chain, safe.address.value, safe.version)
}, [chain, safe.address.value, safe.version, txsWithDetails])

Expand Down
9 changes: 8 additions & 1 deletion src/hooks/coreSDK/safeCoreSDK.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import chains from '@/config/chains'
import { getWeb3 } from '@/hooks/wallets/web3'
import ExternalStore from '@/services/ExternalStore'
import { invariant } from '@/utils/helpers'
import { Web3Provider } from '@ethersproject/providers'
import Safe from '@safe-global/safe-core-sdk'
import type { SafeVersion } from '@safe-global/safe-core-sdk-types'
import EthersAdapter from '@safe-global/safe-ethers-lib'
import type { SafeInfo } from '@safe-global/safe-gateway-typescript-sdk'
import { type EIP1193Provider } from '@web3-onboard/core'
import { ethers } from 'ethers'
import semverSatisfies from 'semver/functions/satisfies'
Expand All @@ -14,11 +16,16 @@ export const isLegacyVersion = (safeVersion: string): boolean => {
return semverSatisfies(safeVersion, LEGACY_VERSION)
}

export const isValidSafeVersion = (safeVersion?: string): safeVersion is SafeVersion => {
export const isValidSafeVersion = (safeVersion?: SafeInfo['version']): safeVersion is SafeVersion => {
const SAFE_VERSIONS: SafeVersion[] = ['1.3.0', '1.2.0', '1.1.1']
return !!safeVersion && SAFE_VERSIONS.some((version) => semverSatisfies(safeVersion, version))
}

// `assert` does not work with arrow functions
export function assertValidSafeVersion<T extends SafeInfo['version']>(safeVersion?: T): asserts safeVersion {
return invariant(isValidSafeVersion(safeVersion), `${safeVersion} is not a valid Safe version`)
}

export const createEthersAdapter = (provider = getWeb3()) => {
if (!provider) {
throw new Error('Unable to create `EthersAdapter` without a provider')
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/coreSDK/useInitSafeCoreSDK.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const useInitSafeCoreSDK = () => {
const dispatch = useAppDispatch()

useEffect(() => {
if (!safeLoaded || !wallet?.provider || safe.chainId !== wallet.chainId) {
if (!safeLoaded || !wallet?.provider || safe.chainId !== wallet.chainId || !safe.version) {
// If we don't reset the SDK, a previous Safe could remain in the store
setSafeSDK(undefined)
return
Expand Down
13 changes: 7 additions & 6 deletions src/services/contracts/safeContracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import type { SafeInfo } from '@safe-global/safe-gateway-typescript-sdk'
import { getMasterCopies, type ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'
import type { GetContractProps, SafeVersion } from '@safe-global/safe-core-sdk-types'
import { type Sign_message_lib } from '@/types/contracts/Sign_message_lib'
import { createEthersAdapter, isValidSafeVersion } from '@/hooks/coreSDK/safeCoreSDK'
import { assertValidSafeVersion, createEthersAdapter } from '@/hooks/coreSDK/safeCoreSDK'
import { sameAddress } from '@/utils/addresses'
import type CompatibilityFallbackHandlerEthersContract from '@safe-global/safe-ethers-lib/dist/src/contracts/CompatibilityFallbackHandler/CompatibilityFallbackHandlerEthersContract'

Expand All @@ -27,11 +27,9 @@ export const isValidMasterCopy = async (chainId: string, address: string): Promi

export const _getValidatedGetContractProps = (
chainId: string,
safeVersion: string,
safeVersion: SafeInfo['version'],
): Pick<GetContractProps, 'chainId' | 'safeVersion'> => {
if (!isValidSafeVersion(safeVersion)) {
throw new Error(`${safeVersion} is not a valid Safe version`)
}
assertValidSafeVersion(safeVersion)

// SDK request here: https://github.com/safe-global/safe-core-sdk/issues/261
// Remove '+L2'/'+Circles' metadata from version
Expand Down Expand Up @@ -125,7 +123,10 @@ export const getMultiSendCallOnlyContractAddress = (chainId: string): string | u
return deployment?.networkAddresses[chainId]
}

export const getMultiSendCallOnlyContractInstance = (chainId: string, safeVersion: string = LATEST_SAFE_VERSION) => {
export const getMultiSendCallOnlyContractInstance = (
chainId: string,
safeVersion: SafeInfo['version'] = LATEST_SAFE_VERSION,
) => {
const ethAdapter = createEthersAdapter()

return ethAdapter.getMultiSendCallOnlyContract({
Expand Down
3 changes: 3 additions & 0 deletions src/services/tx/safeUpdateParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { OperationType } from '@safe-global/safe-core-sdk-types'
import type { ChainInfo, SafeInfo } from '@safe-global/safe-gateway-typescript-sdk'
import { getFallbackHandlerContractInstance, getGnosisSafeContractInstance } from '@/services/contracts/safeContracts'
import { LATEST_SAFE_VERSION } from '@/config/constants'
import { assertValidSafeVersion } from '@/hooks/coreSDK/safeCoreSDK'

// TODO: Check if these are still needed
export const CHANGE_MASTER_COPY_ABI = 'function changeMasterCopy(address _masterCopy)'
Expand All @@ -15,6 +16,8 @@ export const CHANGE_FALLBACK_HANDLER_ABI = 'function setFallbackHandler(address
* Only works for safes < 1.3.0 as the changeMasterCopy function was removed
*/
export const createUpdateSafeTxs = (safe: SafeInfo, chain: ChainInfo): MetaTransactionData[] => {
assertValidSafeVersion(safe.version)

const latestMasterCopy = getGnosisSafeContractInstance(chain, LATEST_SAFE_VERSION)
const safeContractInstance = getGnosisSafeContractInstance(chain, safe.version)

Expand Down
8 changes: 8 additions & 0 deletions src/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// `assert` does not work with arrow functions
export function invariant<T extends unknown>(condition: T, error: string): asserts condition {
if (condition) {
return
}

throw new Error(error)
}
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3275,10 +3275,10 @@
"@safe-global/safe-core-sdk-utils" "^1.5.0"
ethers "^5.7.2"

"@safe-global/safe-gateway-typescript-sdk@^3.5.3":
version "3.5.3"
resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.5.3.tgz#07b5307601ba9d9d0d62f6366fdfc3cdfdfc6f87"
integrity sha512-HzvCmFHw9NEOJK9d3X8nqG3MMuw+/ceccltrgBenHn8OUxNkv8za9jUou0YUmG0HtJ4tKFTW+z8AwpohHTmWAw==
"@safe-global/safe-gateway-typescript-sdk@^3.5.4":
version "3.5.4"
resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.5.4.tgz#daa13d830eb8b6c8f60bf4026be42a9965abcc35"
integrity sha512-olTC+2lxb45MyG5Rxgs0UO1gd3MKYW8ahTvY88nV64KMEbjQQUl0lbQ8VlVT7BZsWuVgG7HshrPDsKU/wPVTeA==
dependencies:
cross-fetch "^3.1.5"

Expand Down

0 comments on commit a7f8712

Please sign in to comment.