The Gnosis Safe is a multisignature wallet with support for confirmations using signed messages based on ERC191. It is the successor of the Gnosis Multisig Wallet and combines more functionality with reduced gas costs. The Gnosis Safe allows basic wallet configuration like adding and removing owners and more advanced features like modules, which allow to do transactions with different requirements.
A Safe transaction has the same parameters as a regular Ethereum transaction: A destination address, an Ether value and a data payload as a bytes array. In addition, Safe transactions have two more parameters: operation
and nonce
.
The operation type specifies if the transaction is executed as a CALL
, DELEGATECALL
or CREATE
operation. While most wallet contracts only support CALL
operations, adding DELEGATECALL
operations allows to enhance the functionality of the wallet without updating the wallet code. As a DELEGATCALL
is executed in the context of the wallet contract, it can potentially mutate the state of the wallet (like changing owners) and therefore can only be used with known, trusted contracts. The CREATE
operation allows to create new contracts with bytecode sent from the wallet itself.
The nonce prevents replay attacks and is increased with every successfully executed Safe transaction. The number of executed Safe transactions is therefore equal to the current nonce saved in the wallet storage.
As the creation of new contracts is a very gas consuming operation, Safe contracts use a proxy pattern where only one master copy of a contract is deployed once and all its copies are deployed as minimal proxy contracts pointing to the master copy contract. This pattern also allows to update the contract functionality later on by updating the address of the master copy in the proxy contract. As contract constructors can only be executed once at the time the master copy is deployed, constructor logic has to be moved into an additional persistent setup function, which can be called to setup all copies of the master copy. This setup function has to be implemented in a way it can only be executed once. It is important to note that the master copy contract has to be persistent and there should be no possibility to execute a selfdestruct
call on the master copy contract.
Multiple contracts use the authorized()
modifier. This modifier should be overwritten by contract to implemented the desired logic to check access to the protected methods.
The self authorized contract implements the authorized()
so that only the contract itself is authorized to perform actions.
The proxy contract implements only two functions: The constructor setting the address of the master copy and the fallback function forwarding all transactions sent to the proxy via a DELEGATECALL
to the master copy and returning all data returned by the DELEGATECALL
.
This is an extension to the proxy contract that allows further initialization logic to be passed to the constructor.
This is an extension to the delegate constructor proxy contract that pays a specific amount to a target address after initialization.
The proxy factory allows to create new proxy contracts pointing to a master copy and executing a function in the newly deployed proxy in one transaction. This additional transaction can for example execute the setup function to initialize the state of the contract.
The master copy contract defines the master copy field and has simple logic to change it. The master copy class should always be defined first if inherited.
The module manager allows the management (add, remove) of modules. These modules can execute transactions via the module manager. The module manager implements logic to execute calls, delegatecalls and create operations.
The owner manager allows the management (add, remove, replace) of owners. It also specifies a threshold that can be used for all actions that require the confirmation of a specific amount of owners.
The Gnosis Safe contract implements all basic multisignature functionality. It allows to execute Safe transactions and Safe modules.
Safe transactions can be used to configure the wallet like managing owners, updating the master copy address or whitelisting of modules. All configuration functions can only be called via transactions sent from the Safe itself. This assures that configuration changes require owner confirmations.
Before a Safe transaction can be executed, the transaction has to be confirmed by the required number of owners.
There are multiple implementations of the Gnosis Safe contract with different methods to check if a transaction has been confirmed by the required owners.
This version is targeted at users that control all keys owning a safe. The transaction hash can be signed with the private keys that manage the safe.
Once the required number of confirmations is available execTransactionAndPaySubmitter
can be called with the sending confirmation signatures. This method will pay the submitter of the transaction for the transaction fees after the Safe transaction has been executed.
execTransactionAndPaySubmitter
expects all confirmations sorted by owner address. This is required to easily validate no confirmation duplicates exist.
This version is targeted at teams where each owner is a different user. Each owner has to confirm a transaction by using confirmTransaction
. Once the required number of owners has confirmed, the transaction can be executed via execTransactionIfApproved
. If the sender of execTransactionIfApproved
is an owner it is not necessary to confirm the transaction before. Furthermore this version doesn't store the nonce in the contract but for each transaction a nonce needs to be specified.
Assuming we have 2 owners in a 2 out of 2 multisig configuration:
0x1
(Private key)0x2
(Private key)
0x1
and 0x2
are confirming by signing a message.
The signatures bytes used for execTransaction
have to be build like the following:
bytes = 0x{r_0x1}{s_0x1}{v_0x1}{r_0x2}{s_0x2}{v_0x2}
v
, r
and s
are the signature parameters for the signed confirmation messages. All values are hex encoded. r
and s
are padded to 32 bytes and v
is padded to 8 bytes.
Modules allow to execute transactions from the Safe without the requirement of multiple signatures. For this Modules that have been added to a Safe can use the execTransactionFromModule
function. Modules define their own requirements for execution. Modules need to implement their own replay protection.
This module is meant to be used with state channels. It is a module similar to the personal edition, but without the payment option (therefore the method is named execTransaction
). Furthermore this version doesn't store the nonce in the contract but for each transaction a nonce needs to be specified.
The Daily Limit Modules allows an owner to withdraw specified amounts of specified ERC20 tokens on a daily basis without confirmation by other owners. The daily limit is reset at midnight UTC. Ether is represented with the token address 0. Daily limits can be set via Safe transactions.
The Social Recovery Modules allows to recover a Safe in case access to owner accounts was lost. This is done by defining a minimum of 3 friends’ addresses as trusted parties. If all required friends confirm that a Safe owner should be replaced with another address, the Safe owner is replaced and access to the Safe can be restored. Every owner address can be replaced only once.
The Whitelist Modules allows an owner to execute arbitrary transactions to specific addresses without confirmation by other owners. The whitelist can be maintained via Safe transactions.
Libraries can be called from the Safe via a DELEGATECALL
. They should not implement their own storage as this storage won’t be accessible via a DELEGATECALL
.
This library allows to batch transactions and execute them at once. This is useful if user interactions require more than one transaction for one UI interaction like approving an amount of ERC20 tokens and calling a contract consuming those tokens. If one transaction fails all are reverted.
This library allows to create new Safe modules and whitelist these modules for the Safe in one single transaction.
To optimize gas usage the naming of the methods was choosen in a matter that result in a low method id for methods that are often used. Please consider this when renaming.
npm install
truffle test
truffle deploy
All contracts are WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
All smart contracts are released under GPL v.3.
- Stefan George (Georgi87)
- Richard Meissner (rmeissner)
- Christian Lundkvist (christianlundkvist)
- Nick Dodson (SilentCicero)
- Gonçalo Sá (GNSPS)