Interact with the Safe API from Foundry scripts.
forge install Recon-Fuzz/safe-utilsimport {Safe} from "safe-utils/Safe.sol";Build the client by passing your safe address.
using Safe for *;
Safe.Client safe;
function setUp() public {
safe.initialize(safeAddress);
}safe.proposeTransaction(weth, abi.encodeCall(IWETH.withdraw, (0)), sender);If you are using ledger, make sure to pass the derivation path as the last argument:
safe.proposeTransaction(weth, abi.encodeCall(IWETH.withdraw, (0)), sender, "m/44'/60'/0'/0/0");Proposing a transaction/transactions using a Ledger will also require pre-computing the signature, due to a (current) limitation with forge.
The first step is to pre-compute the signature:
bytes memory signature = safe.sign(weth, abi.encodeCall(IWETH.withdraw, (0)), Enum.Operation.Call, sender, "m/44'/60'/0'/0/0");Note that this call will fail if forge script is called with the --ledger flag, as that would block this library's contracts from utilising the same device. Instead, pass the Ledger derivation path as an argument to the script.
The second step is to take the value for the returned bytes and provide them when proposing the transaction:
safe.proposeTransactionWithSignature(weth, abi.encodeCall(IWETH.withdraw, (0)), sender, signature);- Foundry with FFI enabled:
- Pass
--ffito your commands (e.g.forge test --ffi) - Or set
ffi = truein yourfoundry.toml
- Pass
[profile.default]
ffi = true- All
Recon-Fuzz/solidity-httpdependencies
https://github.com/Recon-Fuzz/governance-proposals-done-right
This code is provided "as is" and has not undergone a formal security audit.
Use it at your own risk. The author(s) assume no liability for any damages or losses resulting from the use of this code. It is your responsibility to thoroughly review, test, and validate its security and functionality before deploying or relying on it in any environment.
This is not an official @safe-global library