Firm Modules
Last updated
Last updated
FirmBase
is the base contract that Firm modules use which includes all dependencies and handles initialization in a standard way.
All modules must call __init_firmBase
as part of their initialization flow. This method can only be called once and will revert if attempted again (it is used as the implicit guard against re-initialization).
Initialization will set both the Safe and an initial trusted forwarder for meta-txs for the module. It is imperative that these get set to correct and trusted values, given the overarching powers that these two have.
SafeModule
is an optional base contract which only modules which are intended to be a Safe module (have the ability to send transactions through the Safe) should use.
SafeModule
has several internal functions that will allow the module to send transactions through the Safe bypassing Safe owner confirmations.
There’s a special _moduleExecDelegateCallToSelf
method, which will cause the Safe to call back into the code of the module in order to act from the Safe context. This is useful for performing several actions at the same time as it results in considerable gas savings. However it must be noted how critical this is since it will cause the Safe to execute some arbitrary code, it must be used with extreme caution. It is also recommended to always decorate the callback function where the Safe will enter with the onlyForeignContext
modifier.
SafeAware
is the base-most contract. It is responsible for storing at fetching a reference to the address of the Safe.
Other base contracts derive from it so they can perform access control depending on whether the caller is the Safe. The onlySafe
modifier can also be used by modules to protect functions which are only intended to be called by the Safe.
Firm uses the EIP-1967 standard for upgradeability. In our proxies, the implementation address is always stored in the slot defined by EIP-1967.
The implementation contracts themselves are responsible for making changes to that value which will result in an upgrade for the proxy. Since the proxy itself has no logic to handle upgrades, if a proxy is upgraded to a certain implementation address which has no upgrade logic, it will cease being upgradeable.
Firm modules support the ERC-2771 standard to allow for meta-transactions through a compliant relayer.
All modules in initialization should allow for setting an initial trusted forwarder or relay. Once set, the module will accept meta-transactions relayed through that relayer.
The Safe can edit this at any time by adding or removing extra relayers. This is an extremely critical operation, as a rogue relayer will allow impersonating almost all accounts for access control. One exception is the onlySafe
check, which is always performed on msg.sender
and doesn’t support meta-transactions.