safe-global / safe-core-sdk

The Safe{Core} SDK allows builders to add account abstraction functionality into their apps.
https://docs.safe.global/sdk/overview
MIT License
255 stars 202 forks source link

`SafeFactory.deploySafe` should have the option to add modules to a safe on deploy #628

Closed froggiedev closed 10 months ago

froggiedev commented 11 months ago

Context / issue

To improve the user experience of deploying new safes within applications for AA.

In case your feature request related to a problem, please add clear and concise description of what the issue is.

Users have to make too many transactions to prepare a Smart Account for usage as a bundler.

Please add a clear and concise description of what you want to happen.

SafeFactory.deploySafe should have an additional modules: string[] option that is passed to the setup of the safe and automatically enabled after deployment, without requiring a second transaction.

Please add a clear and concise description of any alternative solutions or features you have considered.

Keep the user-experience poor.

valeryz commented 11 months ago

You can do this by passing suitable to and data arguments to deploySafe, and adding the follwoing to your module:

import "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol";

contract MyAwesomeModule {
    ...
    // Can only be called as delegatecall from a GnosisSafe during setup.
    function enableModule(address module) external {
        address payable thisAddr = payable(address(this));
        GnosisSafe(thisAddr).enableModule(module);
    }
   ...
}

then you first create your module, then deploy:

       const iface = new ethers.utils.Interface(["function enableModule(address module)"]);
       const safeAccountConfig: SafeAccountConfig =  {
           owners: owners,
           threshold: <threhold>,
           to: myAwesomeModule.address,
           data: iface.encodeFunctionData("enableModule", [myAwesomeModule.address])
       };

       safe = await safeFactory.deploySafe({ safeAccountConfig });

it will delegatecall into your module while allowing you do to anything as initial set up of the Safe.

froggiedev commented 10 months ago

You can do this by passing suitable to and data arguments to deploySafe, and adding the follwoing to your module:

import "@gnosis.pm/safe-contracts/contracts/GnosisSafe.sol";

contract MyAwesomeModule {
    ...
    // Can only be called as delegatecall from a GnosisSafe during setup.
    function enableModule(address module) external {
        address payable thisAddr = payable(address(this));
        GnosisSafe(thisAddr).enableModule(module);
    }
   ...
}

then you first create your module, then deploy:

       const iface = new ethers.utils.Interface(["function enableModule(address module)"]);
       const safeAccountConfig: SafeAccountConfig =  {
           owners: owners,
           threshold: <threhold>,
           to: myAwesomeModule.address,
           data: iface.encodeFunctionData("enableModule", [myAwesomeModule.address])
       };

       safe = await safeFactory.deploySafe({ safeAccountConfig });

it will delegatecall into your module while allowing you do to anything as initial set up of the Safe.

Perfect, thanks.

ashwinYardi commented 9 months ago

hey guys, I have a doubt related to the method being used here for enabling a module.

As per the discussion:

Am I missing anything?

@froggiedev @valeryz