Safe Management
This guide explains how to modify your Safe configuration programmatically.
Working with Safe Contracts
You can directly access the underlying Safe protocol smart contract via safe.contract
:
# Accessible as `safe.signers`
owners = safe.contract.getOwners()
assert owners == safe.signers
# Accessible as `safe.confirmations_required`
threshold = safe.contract.getThreshold()
assert threshold == safe.confirmations_required
Changing Safe Ownership and Threshold
Using the Safe contract provides methods to modify the Safe’s owner set:
# Add a new owner with the current threshold
receipt = safe.contract.addOwnerWithThreshold(
"0xNewOwnerAddress",
safe.confirmations_required, # NOTE: Can also change threshold as the same time
sender=safe
)
# Remove an owner
prev_owner = safe.compute_prev_signer("0xOwnerToRemove")
receipt = safe.contract.removeOwner(
safe.compute_prev_signer("0xOwnerToRemove"),
"0xOwnerToRemove",
safe.confirmations_required, # NOTE: Can also change threshold as the same time
sender=safe
)
# Swap an owner
prev_owner = safe.compute_prev_signer("0xOldOwner")
receipt = safe.contract.swapOwner(
safe.compute_prev_signer("0xOwnerToRemove"),
"0xOldOwner",
"0xNewOwner",
# NOTE: Cannot modify threshold this way
sender=safe
)
# Change threshold
receipt = safe.contract.changeThreshold(
new_threshold,
sender=safe
)
Note that these are multisig transactions themselves and require the appropriate number of confirmations.
Safe Modules
The Safe protocol supports configuring “Modules”, which are contracts that have special capabilities to access your Safe.
You can enable or disable modules using the Safe contract as followsnot :
assert not safe.contract.isModuleEnabled("0xModule")
safe.contract.enableModule("0xModule", sender=safe)
assert safe.contract.isModuleEnabled("0xModule")
safe.contract.disableModule("0xModule", sender=safe)
assert not safe.contract.isModuleEnabled("0xModule")
Safe Guard
Since version v1.3.0, the Safe protocol supports setting a transaction “Guard”, which is a contract that can disallow certain actions to occur unless conditions are met after a proposed transaction executes.
To check if your safe has a Guard implemented, you can use the .guard
property, which will return a contract if the guard is set.
You can also change or set a guard using the .set_guard
function:
assert not safe.guard
safe.set_guard("0xMyGuard", submitter=me)
assert safe.guard
Warning
Setting a Guard is a dangerous action. Do NOT attempt unless you know what you are doing. If a Guard is set improperly, it may render your Safe (and all it’s assets) permanently inaccessible.
Understanding Safe Versions
Safe contracts have different versions with varying features. Ape Safe supports all major Safe versions:
Safe v1.1.1
Safe v1.3.0
Safe v1.4.1
You can check the version of your Safe by examining the master copy address when listing Safes with the --verbose
flag.