Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include setMultisend on the setup stack #161

Merged
merged 2 commits into from
Nov 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 11 additions & 11 deletions packages/app/src/services/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { Contract } from "ethers";
import { abi as SafeAbi } from "@gnosis.pm/safe-deployments/dist/assets/v1.3.0/gnosis_safe_l2.json";
import { Interface } from "@ethersproject/abi"
import { abi as SafeAbi } from "@gnosis.pm/safe-deployments/dist/assets/v1.3.0/gnosis_safe_l2.json"

export const AddressOne = "0x0000000000000000000000000000000000000001";
export const AddressOne = "0x0000000000000000000000000000000000000001"

export const buildTransaction = (
contract: Contract,
iface: Interface,
to: string,
method: string,
params: any[],
value?: string
value?: string,
) => {
let data = contract.interface.encodeFunctionData(method, params);
return {
to: contract.address,
data,
to,
data: iface.encodeFunctionData(method, params),
value: value || "0",
};
};
}
}

export { SafeAbi };
export { SafeAbi }
108 changes: 47 additions & 61 deletions packages/app/src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { BigNumber, Contract, ethers } from "ethers"
import { Interface } from "@ethersproject/abi"
import {
calculateProxyAddress,
deployAndSetUpModule,
Expand Down Expand Up @@ -53,6 +54,7 @@ interface DelayModuleParams {

export interface RolesModifierParams {
target: string
multisend: string
}

export interface AMBModuleParams {
Expand Down Expand Up @@ -199,18 +201,16 @@ export function deployTellorModule(

if (executor !== safeAddress) {
const delayModule = getModuleInstance(KnownContracts.DELAY, executor, provider)
const addModuleTransaction = buildTransaction(delayModule, "enableModule", [
daoModuleExpectedAddress,
])
const addModuleTransaction = buildTransaction(
delayModule.interface,
delayModule.address,
"enableModule",
[daoModuleExpectedAddress],
)

daoModuleTransactions.push(addModuleTransaction)
} else {
const enableDaoModuleTransaction = enableModule(
provider,
safeAddress,
chainId,
daoModuleExpectedAddress,
)
const enableDaoModuleTransaction = enableModule(safeAddress, daoModuleExpectedAddress)
daoModuleTransactions.push(enableDaoModuleTransaction)
}

Expand Down Expand Up @@ -238,9 +238,7 @@ export function deployDelayModule(
Date.now().toString(),
)
const enableDelayModuleTransaction = enableModule(
provider,
safeAddress,
chainId,
delayModuleExpectedAddress,
)

Expand Down Expand Up @@ -279,12 +277,7 @@ export function deployBridgeModule(
Date.now().toString(),
)

const enableModuleTransaction = enableModule(
provider,
safeAddress,
chainId,
expectedModuleAddress,
)
const enableModuleTransaction = enableModule(safeAddress, expectedModuleAddress)

return [
{
Expand Down Expand Up @@ -400,12 +393,7 @@ export async function deployExitModule(
value: transaction.value.toString(),
})

const enableModuleTransaction = enableModule(
provider,
safeAddress,
chainId,
expectedModuleAddress,
)
const enableModuleTransaction = enableModule(safeAddress, expectedModuleAddress)
txs.push(enableModuleTransaction)

return txs
Expand All @@ -421,14 +409,8 @@ export async function fetchSafeModulesAddress(
return modules as string[]
}

export function enableModule(
provider: JsonRpcProvider,
safeAddress: string,
chainId: number,
module: string,
) {
const safe = new Contract(safeAddress, SafeAbi, provider)
return buildTransaction(safe, "enableModule", [module])
export function enableModule(safeAddress: string, module: string) {
return buildTransaction(new Interface(SafeAbi), safeAddress, "enableModule", [module])
}

export async function disableModule(
Expand All @@ -440,15 +422,14 @@ export async function disableModule(
const modules = await fetchSafeModulesAddress(provider, safeAddress, chainId)
if (!modules.length) throw new Error("Safe does not have enabled modules")
let prevModule = AddressOne
const safe = new Contract(safeAddress, SafeAbi, provider)
if (modules.length > 1) {
const moduleIndex = modules.findIndex((m) => m.toLowerCase() === module.toLowerCase())
if (moduleIndex > 0) prevModule = modules[moduleIndex - 1]
}
const params = [prevModule, module]
return {
params,
...buildTransaction(safe, "disableModule", params),
...buildTransaction(new Interface(SafeAbi), safeAddress, "disableModule", params),
}
}

Expand Down Expand Up @@ -502,33 +483,40 @@ export function deployRolesModifier(
chainId: number,
args: RolesModifierParams,
) {
const { target } = args
const {
transaction: rolesModifierDeploymentTx,
expectedModuleAddress: rolesModifierExpectedAddress,
} = deployAndSetUpModule(
const { target, multisend } = args
const { transaction: deployAndSetupTx, expectedModuleAddress: expectedRolesAddress } =
deployAndSetUpModule(
KnownContracts.ROLES,
{
types: ["address", "address", "address"],
values: [safeAddress, safeAddress, target],
},
provider,
chainId,
Date.now().toString(),
)
const enableModuleTx = enableModule(safeAddress, expectedRolesAddress)

const rolesContract = getModuleInstance(
KnownContracts.ROLES,
{
types: ["address", "address", "address"],
values: [safeAddress, safeAddress, target],
},
expectedRolesAddress,
provider,
chainId,
Date.now().toString(),
)
const enableRolesModifierTransaction = enableModule(
provider,
safeAddress,
chainId,
rolesModifierExpectedAddress,

const setMultisendTx = buildTransaction(
rolesContract.interface,
rolesContract.address,
"setMultisend",
[multisend],
)

return [
{
...rolesModifierDeploymentTx,
value: rolesModifierDeploymentTx.value.toString(),
...deployAndSetupTx,
value: String(deployAndSetupTx.value),
},
enableRolesModifierTransaction,
enableModuleTx,
setMultisendTx,
]
}

Expand Down Expand Up @@ -567,18 +555,16 @@ export function deployOptimisticGovernorModule(

if (executor !== safeAddress) {
const delayModule = getModuleInstance(KnownContracts.DELAY, executor, provider)
const addModuleTransaction = buildTransaction(delayModule, "enableModule", [
daoModuleExpectedAddress,
])
const addModuleTransaction = buildTransaction(
delayModule.interface,
delayModule.address,
"enableModule",
[daoModuleExpectedAddress],
)

daoModuleTransactions.push(addModuleTransaction)
} else {
const enableDaoModuleTransaction = enableModule(
provider,
safeAddress,
chainId,
daoModuleExpectedAddress,
)
const enableDaoModuleTransaction = enableModule(safeAddress, daoModuleExpectedAddress)
daoModuleTransactions.push(enableDaoModuleTransaction)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { addTransaction } from "../../../../store/transactionBuilder"
import { SafeAbi } from "../../../../services/helpers"
import { serializeTransaction } from "../../../../store/transactionBuilder/helpers"
import { ReactComponent as ArrowUpIcon } from "../../../../assets/icons/arrow-up-icon.svg"
import useSafeAppsSDKWithProvider from "hooks/useSafeAppsSDKWithProvider"
import { useSafeAppsSDK } from "@gnosis.pm/safe-apps-react-sdk"

interface AddCustomModuleProps {
open: boolean
Expand All @@ -36,7 +36,7 @@ const useStyles = makeStyles((theme) => ({
}))

export const CustomModuleModal = ({ onSubmit, open, onClose }: AddCustomModuleProps) => {
const { sdk, safe, provider } = useSafeAppsSDKWithProvider()
const { sdk, safe } = useSafeAppsSDK()
const dispatch = useRootDispatch()
const classes = useStyles()

Expand All @@ -55,7 +55,7 @@ export const CustomModuleModal = ({ onSubmit, open, onClose }: AddCustomModulePr
}

const addModule = async () => {
const tx = enableModule(provider, safe.safeAddress, safe.chainId, moduleAddress)
const tx = enableModule(safe.safeAddress, moduleAddress)

try {
await sdk.txs.send({ txs: [tx] })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,16 @@ export async function deployRealityModule(

if (executor !== safeAddress) {
const delayModule = getModuleInstance(KnownContracts.DELAY, executor, provider)
const addModuleTransaction = buildTransaction(delayModule, "enableModule", [
expectedModuleAddress,
])
const addModuleTransaction = buildTransaction(
delayModule.interface,
delayModule.address,
"enableModule",
[expectedModuleAddress],
)

daoModuleTransactions.push(addModuleTransaction)
} else {
const enableDaoModuleTransaction = enableModule(
provider,
safeAddress,
chainId,
expectedModuleAddress,
)
const enableDaoModuleTransaction = enableModule(safeAddress, expectedModuleAddress)
daoModuleTransactions.push(enableDaoModuleTransaction)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,18 +85,16 @@ export function deployRealityModule(

if (executor !== safeAddress) {
const delayModule = getModuleInstance(KnownContracts.DELAY, executor, provider)
const addModuleTransaction = buildTransaction(delayModule, "enableModule", [
daoModuleExpectedAddress,
])
const addModuleTransaction = buildTransaction(
delayModule.interface,
delayModule.address,
"enableModule",
[daoModuleExpectedAddress],
)

daoModuleTransactions.push(addModuleTransaction)
} else {
const enableDaoModuleTransaction = enableModule(
provider,
safeAddress,
chainId,
daoModuleExpectedAddress,
)
const enableDaoModuleTransaction = enableModule(safeAddress, daoModuleExpectedAddress)
daoModuleTransactions.push(enableDaoModuleTransaction)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { deployRolesModifier, RolesModifierParams } from "services"
import { ParamInput } from "../../../../components/ethereum/ParamInput"
import { ParamType } from "@ethersproject/abi"
import useSafeAppsSDKWithProvider from "hooks/useSafeAppsSDKWithProvider"
import { SafeInfo } from "@gnosis.pm/safe-apps-sdk"
import {
networkAddresses as multisendNetworkAddresses,
defaultAddress as defaultMultisendAddress,
} from "@gnosis.pm/safe-deployments/dist/assets/v1.3.0/multi_send.json"

interface RolesModifierModalProps {
open: boolean
Expand Down Expand Up @@ -34,9 +39,11 @@ export const RolesModifierModal = ({

const [errors, setErrors] = useState<Record<keyof RolesModifierParams, boolean>>({
target: true,
multisend: true,
})
const [params, setParams] = useState<RolesModifierParams>({
target: safe.safeAddress,
multisend: defaultMultisend(safe),
})

const isValid = Object.values(errors).every((field) => field)
Expand Down Expand Up @@ -90,7 +97,22 @@ export const RolesModifierModal = ({
onChange={(value, valid) => onParamChange("target", value, valid)}
/>
</Grid>
<Grid item xs={12}>
<ParamInput
param={ParamType.from("address")}
color="secondary"
value={params.multisend}
label="Multisend Address"
onChange={(value, valid) => onParamChange("target", value, valid)}
/>
</Grid>
</Grid>
</AddModuleModal>
)
}

function defaultMultisend(safeInfo: SafeInfo) {
const address = (multisendNetworkAddresses as Record<string, string>)[safeInfo.chainId]

return address || defaultMultisendAddress
}