Firm Modules

Firm Base

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.

Safe Module

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.

Safe Aware

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.

EIP-1967 upgradeable proxies

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.

ERC-2771 context

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.

Last updated