Skip to content

Commit

Permalink
hotfix for direct exec as safe owner #352
Browse files Browse the repository at this point in the history
  • Loading branch information
jfschwarz committed Dec 17, 2024
1 parent cda1c65 commit 2a4f33b
Show file tree
Hide file tree
Showing 15 changed files with 273 additions and 187 deletions.
2 changes: 1 addition & 1 deletion extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"react-dom": "^18.2.0",
"react-select": "5.8.3",
"rimraf": "6.0.1",
"ser-kit": "^0.3.17",
"ser-kit": "1.0.6",
"tailwindcss": "^3.4.14",
"typescript": "^5.5.4",
"typescript-eslint": "^7.16.0",
Expand Down
349 changes: 208 additions & 141 deletions extension/pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions extension/src/chains/getChainId.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { invariant } from '@epic-web/invariant'
import { parsePrefixedAddress, PrefixedAddress } from 'ser-kit'
import { PrefixedAddress, splitPrefixedAddress } from 'ser-kit'

export const getChainId = (address: PrefixedAddress) => {
// atm, we don't yet support cross-chain routes, so can derive a general chainId from the avatar
const [chainId] = parsePrefixedAddress(address)
const [chainId] = splitPrefixedAddress(address)

invariant(chainId != null, 'chainId is empty')

Expand Down
4 changes: 2 additions & 2 deletions extension/src/panel/execution-routes/useRouteConnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isConnected, useInjectedWallet, useWalletConnect } from '@/providers'
import { ExecutionRoute, ProviderType } from '@/types'
import { ZeroAddress } from 'ethers'
import { useCallback } from 'react'
import { parsePrefixedAddress } from 'ser-kit'
import { splitPrefixedAddress } from 'ser-kit'
import { useProviderChainId } from './useProviderChainId'

export const useRouteConnect = (route: ExecutionRoute) => {
Expand Down Expand Up @@ -63,7 +63,7 @@ const useCanEstablishConnection = (route: ExecutionRoute) => {

const pilotAddress =
route.initiator && route.initiator !== `eoa:` + ZeroAddress
? parsePrefixedAddress(route.initiator)[1].toLowerCase()
? splitPrefixedAddress(route.initiator)[1].toLowerCase()
: undefined

if (pilotAddress == null) {
Expand Down
4 changes: 2 additions & 2 deletions extension/src/panel/integrations/zodiac/useZodiacModules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { selectorsFromBytecode } from '@shazow/whatsabi'
import { Contract, id, Interface, ZeroAddress } from 'ethers'
import detectProxyTarget from 'evm-proxy-detection'
import { useEffect, useState } from 'react'
import { ChainId, parsePrefixedAddress, PrefixedAddress } from 'ser-kit'
import { ChainId, PrefixedAddress, splitPrefixedAddress } from 'ser-kit'
import { SupportedModuleType } from './types'

const SUPPORTED_MODULES = [
Expand All @@ -32,7 +32,7 @@ export const useZodiacModules = (
const [error, setError] = useState(false)
const [modules, setModules] = useState<Module[]>([])
const chainId = getChainId(safeAddress)
const [, address] = parsePrefixedAddress(safeAddress)
const [, address] = splitPrefixedAddress(safeAddress)

useEffect(() => {
setLoading(true)
Expand Down
4 changes: 2 additions & 2 deletions extension/src/panel/pages/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from '@/providers'
import { useProvider } from '@/providers-ui'
import { Outlet } from 'react-router-dom'
import { parsePrefixedAddress } from 'ser-kit'
import { splitPrefixedAddress } from 'ser-kit'
import { useStorage } from '../utils'
import {
asLegacyConnection,
Expand All @@ -27,7 +27,7 @@ export const Root = () => {

const chainId = getChainId(route.avatar)
const provider = useProvider()
const [, avatarAddress] = parsePrefixedAddress(route.avatar)
const [, avatarAddress] = splitPrefixedAddress(route.avatar)
const saveRoute = useSaveExecutionRoute()

useProviderBridge({ provider, chainId, account: avatarAddress })
Expand Down
37 changes: 19 additions & 18 deletions extension/src/panel/pages/legacyConnectionMigrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@ import { ZeroAddress } from 'ethers'
import {
AccountType,
ConnectionType,
Delay,
formatPrefixedAddress,
parsePrefixedAddress,
Roles,
PrefixedAddress,
splitPrefixedAddress,
Waypoint,
} from 'ser-kit'

Expand Down Expand Up @@ -42,33 +41,33 @@ export function fromLegacyConnection(
const delayModuleWaypoint = moduleType === KnownContracts.DELAY && {
account: {
type: AccountType.DELAY,
prefixedAddress: modulePrefixedAddress,
prefixedAddress: modulePrefixedAddress?.toLowerCase(),
address: connection.moduleAddress,
chain: chainId,
} as Delay,
},

connection: {
type: ConnectionType.IS_ENABLED,
from: pilotPrefixedAddress,
from: pilotPrefixedAddress.toLowerCase(),
},
}

const rolesModuleWaypoint = (moduleType === KnownContracts.ROLES_V1 ||
moduleType === KnownContracts.ROLES_V2) && {
account: {
type: AccountType.ROLES,
prefixedAddress: modulePrefixedAddress,
prefixedAddress: modulePrefixedAddress?.toLowerCase(),
address: connection.moduleAddress,
chain: chainId,
version: moduleType === KnownContracts.ROLES_V1 ? 1 : 2,
multisend: [connection.multisend, connection.multisendCallOnly].filter(
Boolean
) as `0x${string}`[],
} as Roles,
},
connection: pilotPrefixedAddress
? {
type: ConnectionType.IS_MEMBER,
from: pilotPrefixedAddress,
from: pilotPrefixedAddress.toLowerCase(),
roles: [connection.roleId].filter(Boolean) as string[],
}
: undefined,
Expand All @@ -81,12 +80,12 @@ export function fromLegacyConnection(
account: isEoa
? ({
type: AccountType.EOA,
prefixedAddress: pilotPrefixedAddress,
prefixedAddress: pilotPrefixedAddress?.toLowerCase(),
address: pilotAddress,
} as const)
: ({
type: AccountType.SAFE,
prefixedAddress: pilotPrefixedAddress,
prefixedAddress: pilotPrefixedAddress?.toLowerCase(),
address: pilotAddress,
chain: chainId,
threshold: NaN, // we don't know the threshold
Expand All @@ -98,19 +97,19 @@ export function fromLegacyConnection(
{
account: {
type: AccountType.SAFE,
prefixedAddress: avatarPrefixedAddress,
prefixedAddress: avatarPrefixedAddress.toLowerCase(),
address: avatarAddress,
chain: chainId,
threshold: NaN, // we don't know the threshold
},
connection: modulePrefixedAddress
? {
type: ConnectionType.IS_ENABLED,
from: modulePrefixedAddress,
from: modulePrefixedAddress.toLowerCase(),
}
: {
type: ConnectionType.OWNS,
from: pilotPrefixedAddress,
from: pilotPrefixedAddress.toLowerCase(),
},
} as Waypoint,
]
Expand All @@ -121,8 +120,10 @@ export function fromLegacyConnection(
lastUsed: connection.lastUsed,
providerType,
waypoints: waypoints as ExecutionRoute['waypoints'],
initiator: pilotAddress ? pilotPrefixedAddress : undefined,
avatar: avatarPrefixedAddress,
initiator: pilotAddress
? (pilotPrefixedAddress.toLowerCase() as PrefixedAddress)
: undefined,
avatar: avatarPrefixedAddress.toLowerCase() as PrefixedAddress,
}
}

Expand All @@ -131,15 +132,15 @@ export function asLegacyConnection(route: ExecutionRoute): LegacyConnection {
throw new Error('Not representable as legacy connection')
}

const [chainId, avatarAddressChecksummed] = parsePrefixedAddress(route.avatar)
const [chainId, avatarAddressChecksummed] = splitPrefixedAddress(route.avatar)
const avatarAddress = avatarAddressChecksummed.toLowerCase()
if (!chainId) {
throw new Error('chainId is empty')
}

const pilotAddress =
(route.initiator &&
parsePrefixedAddress(route.initiator)[1].toLowerCase()) ||
splitPrefixedAddress(route.initiator)[1].toLowerCase()) ||
''

const moduleWaypoint = route.waypoints?.find(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
} from '@/providers'
import { ExecutionRoute, ProviderType } from '@/types'
import { ZeroAddress } from 'ethers'
import { ChainId, parsePrefixedAddress } from 'ser-kit'
import { ChainId, splitPrefixedAddress } from 'ser-kit'
import { InjectedWallet, InjectedWalletConnect } from './injectedWallet'
import { WalletConnect, WalletConnectConnect } from './walletConnect'

Expand Down Expand Up @@ -96,7 +96,7 @@ const getPilotAddress = (route: ExecutionRoute) => {
return null
}

const address = parsePrefixedAddress(route.initiator)[1].toLowerCase()
const address = splitPrefixedAddress(route.initiator)[1].toLowerCase()

if (address === ZeroAddress) {
return null
Expand Down
17 changes: 14 additions & 3 deletions extension/src/panel/pages/transactions/RolePermissionCheck.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ import { Check, TriangleAlert, UsersRound } from 'lucide-react'
import { useEffect, useState } from 'react'
import {
ExecutionActionType,
parsePrefixedAddress,
planExecution,
PrefixedAddress,
Route as SerRoute,
splitPrefixedAddress,
} from 'ser-kit'
import { Translate } from './Translate'

Expand All @@ -29,7 +30,17 @@ const simulateRolesTransaction = async (
const routeWithInitiator = (
route.initiator ? route : { ...route, initiator: ZeroAddress }
) as SerRoute
const plan = await planExecution([encodedTransaction], routeWithInitiator)
const plan = await planExecution(
[
{
to: encodedTransaction.to as `0x${string}`,
data: encodedTransaction.to as `0x${string}`,
operation: encodedTransaction.operation,
value: BigInt(encodedTransaction.value),
},
],
routeWithInitiator
)

// TODO generalize permission checking logic (ser-kit)
if (plan.length > 1) {
Expand All @@ -40,7 +51,7 @@ const simulateRolesTransaction = async (
throw new Error('Only transaction execution is currently supported')
}

const [, from] = parsePrefixedAddress(plan[0].from)
const [, from] = splitPrefixedAddress(plan[0].from as PrefixedAddress)
const tx = {
...plan[0].transaction,
from,
Expand Down
4 changes: 2 additions & 2 deletions extension/src/panel/pages/transactions/Submit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { invariant } from '@epic-web/invariant'
import { SquareArrowOutUpRight } from 'lucide-react'
import { useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { parsePrefixedAddress, PrefixedAddress } from 'ser-kit'
import { PrefixedAddress, splitPrefixedAddress } from 'ser-kit'

export const Submit = () => {
const route = useExecutionRoute()
Expand Down Expand Up @@ -107,7 +107,7 @@ export const Submit = () => {
console.debug(
`Transaction batch has been proposed with safeTxHash ${safeTxHash}`
)
const [, avatarAddress] = parsePrefixedAddress(avatar)
const [, avatarAddress] = splitPrefixedAddress(avatar)
successToast({
title: 'Transaction batch has been proposed for execution',
message: (
Expand Down
6 changes: 3 additions & 3 deletions extension/src/panel/providers-ui/ProvideProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
useEffect,
useState,
} from 'react'
import { ConnectionType, parsePrefixedAddress } from 'ser-kit'
import { ConnectionType, splitPrefixedAddress } from 'ser-kit'
import { ExecutionStatus, useDispatch } from '../state'
import { fetchContractInfo } from '../utils/abi'
import { ProvideSubmitTransactionContext } from './SubmitTransactionContext'
Expand All @@ -28,7 +28,7 @@ export const ProvideProvider = ({ children }: PropsWithChildren) => {

const dispatch = useDispatch()

const [, avatarAddress] = parsePrefixedAddress(route.avatar)
const [, avatarAddress] = splitPrefixedAddress(route.avatar)
const avatarWaypoint = route.waypoints?.[route.waypoints.length - 1]
const connectionType =
avatarWaypoint &&
Expand All @@ -37,7 +37,7 @@ export const ProvideProvider = ({ children }: PropsWithChildren) => {
const [, connectedFrom] =
(avatarWaypoint &&
'connection' in avatarWaypoint &&
parsePrefixedAddress(avatarWaypoint.connection.from)) ||
splitPrefixedAddress(avatarWaypoint.connection.from)) ||
[]

const moduleAddress =
Expand Down
13 changes: 10 additions & 3 deletions extension/src/panel/providers-ui/SubmitTransactionContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ export const ProvideSubmitTransactionContext = ({
throw new Error('Cannot execute without a connected Pilot wallet')
}

const plan = await planExecution(metaTransactions, route as Route)
const plan = await planExecution(
metaTransactions.map((tx) => ({
to: tx.to as `0x${string}`,
data: tx.to as `0x${string}`,
operation: tx.operation,
value: BigInt(tx.value),
})),
route as Route
)
console.debug('Execution plan:', plan)

const state = [] as ExecutionState
Expand All @@ -58,8 +66,7 @@ export const ProvideSubmitTransactionContext = ({
const safeTxHash =
state[
plan.findLastIndex(
(action) =>
action.type === ExecutionActionType.PROPOSE_SAFE_TRANSACTION
(action) => action.type === ExecutionActionType.PROPOSE_TRANSACTION
)
]
const txHash =
Expand Down
4 changes: 2 additions & 2 deletions extension/src/panel/providers/isConnected.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChainId, parsePrefixedAddress, PrefixedAddress } from 'ser-kit'
import { ChainId, PrefixedAddress, splitPrefixedAddress } from 'ser-kit'
import { ConnectionProvider } from './connectTypes'

export const isConnected = (
Expand All @@ -14,7 +14,7 @@ export const isConnected = (
return false
}

const [, accountAddress] = parsePrefixedAddress(account)
const [, accountAddress] = splitPrefixedAddress(account)

return connection.accounts.some(
(account) => account.toLowerCase() === accountAddress.toLowerCase()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { TransactionState, useDispatch, useTransactions } from '@/state'
import { invariant } from '@epic-web/invariant'
import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'
import { useCallback, useEffect, useState } from 'react'
import { ChainId, parsePrefixedAddress } from 'ser-kit'
import { ChainId, splitPrefixedAddress } from 'ser-kit'
import {
ApplicableTranslation,
applicableTranslationsCache,
Expand All @@ -21,7 +21,7 @@ export const useApplicableTranslation = (transactionId: string) => {

const dispatch = useDispatch()
const { avatar } = useExecutionRoute()
const [_, avatarAddress] = parsePrefixedAddress(avatar)
const [_, avatarAddress] = splitPrefixedAddress(avatar)

const [translation, setTranslation] = useState<
ApplicableTranslation | undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useProvider } from '@/providers-ui'
import { TransactionState, useDispatch, useTransactions } from '@/state'
import { MetaTransactionData } from '@safe-global/safe-core-sdk-types'
import { useCallback, useEffect } from 'react'
import { ChainId, parsePrefixedAddress } from 'ser-kit'
import { ChainId, splitPrefixedAddress } from 'ser-kit'
import {
ApplicableTranslation,
applicableTranslationsCache,
Expand All @@ -19,7 +19,7 @@ export const useGloballyApplicableTranslation = () => {
const dispatch = useDispatch()
const { avatar } = useExecutionRoute()
const chainId = getChainId(avatar)
const [_, avatarAddress] = parsePrefixedAddress(avatar)
const [_, avatarAddress] = splitPrefixedAddress(avatar)

const apply = useCallback(
async (translation: ApplicableTranslation) => {
Expand Down

0 comments on commit 2a4f33b

Please sign in to comment.