Gnosis Safe
Docs
Source
ChefGPT

Collection of production code that is used in the Safe Ecosystem

Safe :
Most important concepts: - Threshold: Number of required confirmations for a Safe transaction. - Owners: List of addresses that control the Safe. They are the only ones that can add/remove owners, change the threshold and approve transactions. Managed in `OwnerManager`. - Transaction Hash: Hash of a transaction is calculated using the EIP-712 typed structured data hashing scheme. - Nonce: Each transaction should have a different nonce to prevent replay attacks. - Signature: A valid signature of an owner of the Safe for a transaction hash. - Guard: Guard is a contract that can execute pre- and post- transaction checks. Managed in `GuardManager`. - Modules: Modules are contracts that can be used to extend the write functionality of a Safe. Managed in `ModuleManager`. - Fallback: Fallback handler is a contract that can provide additional read-only functional for Safe. Managed in `FallbackManager`. Note: This version of the implementation contract doesn't emit events for the sake of gas efficiency and therefore requires a tracing node for indexing/ For the events-based implementation see `SafeL2.sol`.
addOwnerWithThreshold(address,uint256) :
This can only be done via a Safe transaction.
approveHash(bytes32) :
This can be used with a pre-approved hash transaction signature. IMPORTANT: The approved hash stays approved forever. There's no revocation mechanism, so it behaves similarly to ECDSA signatures
changeThreshold(uint256) :
This can only be done via a Safe transaction.
checkNSignatures(bytes32,bytes,bytes,uint256) :
Since the EIP-1271 does an external call, be mindful of reentrancy attacks.
disableModule(address,address) :
This can only be done via a Safe transaction.
domainSeparator() :
Returns the domain separator for this contract, as defined in the EIP-712 standard.
enableModule(address) :
This can only be done via a Safe transaction.
execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes) :
The fees are always transferred, even if the user transaction fails. This method doesn't perform any sanity check of the transaction, such as: - if the contract at `to` address has code or not - if the `gasToken` is a contract or not It is the responsibility of the caller to perform such checks.
execTransactionFromModule(address,uint256,bytes,uint8) :
Function is virtual to allow overriding for L2 singleton to emit an event for indexing.
removeOwner(address,address,uint256) :
This can only be done via a Safe transaction.
setFallbackHandler(address) :
Only fallback calls without value and with data will be forwarded. This can only be done via a Safe transaction. Cannot be set to the Safe itself.
setGuard(address) :
Set a guard that checks transactions before execution This can only be done via a Safe transaction. ⚠️ IMPORTANT: Since a guard has full power to block Safe transaction execution, a broken guard can cause a denial of service for the Safe. Make sure to carefully audit the guard code and design recovery mechanisms.
setup(address[],uint256,address,bytes,address,address,uint256,address) :
This method can only be called once. If a proxy was created without setting up, anyone can call setup and claim the proxy.
simulateAndRevert(address,bytes) :
Performs a delegatecall on a targetContract in the context of self. Internally reverts execution to avoid side effects (making it static). This method reverts with data equal to `abi.encode(bool(success), bytes(response))`. Specifically, the `returndata` after a call to this method will be: `success:bool || response.length:uint256 || response:bytes`.
swapOwner(address,address,address) :
This can only be done via a Safe transaction.
OwnerManager :
Uses a linked list to store the owners because the code generate by the solidity compiler is more efficient than using a dynamic array.
addOwnerWithThreshold(address,uint256) :
This can only be done via a Safe transaction.
changeThreshold(uint256) :
This can only be done via a Safe transaction.
removeOwner(address,address,uint256) :
This can only be done via a Safe transaction.
swapOwner(address,address,address) :
This can only be done via a Safe transaction.
DebugTransactionGuard :
This guard is only meant as a development tool and example
supportsInterface(bytes4) :
Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding EIP section https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified to learn more about how these ids are created. This function call must use less than 30 000 gas.
HandlerContext :
The fallback manager appends the following context to the calldata: 1. Fallback manager caller address (non-padded) based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/f8cc8b844a9f92f63dc55aa581f7d643a1bc5ac1/contracts/metatx/ERC2771Context.sol
ERC721TokenReceiver :
Note: the ERC-165 identifier for this interface is 0x150b7a02.
onERC721Received(address,address,uint256,bytes) :
The ERC721 smart contract calls this function on the recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return of other than the magic value MUST result in the transaction being reverted. Note: the contract address is always the message sender.
ERC777TokensRecipient :
Interface for contracts that will be called with the ERC777 token's `tokensReceived` method. The contract receiving the tokens must implement this interface in order to receive the tokens.
tokensReceived(address,address,address,uint256,bytes,bytes) :
Called by the ERC777 token contract after a successful transfer or a minting operation.
SafeStorage :
Should be always the first base contract of a library that is used with a Safe.
IProxyCreationCallback :
An interface for a contract that implements a callback function to be executed after the creation of a proxy instance.
proxyCreated(address,address,bytes,uint256) :
Function to be called after the creation of a SafeProxy instance.
Safe.sol
SafeL2.sol
SimulateTxAccessor.sol
Executor.sol
FallbackManager.sol
GuardManager.sol
ModuleManager.sol
OwnerManager.sol
Enum.sol
NativeCurrencyPaymentFallback.sol
SecuredTokenTransfer.sol
SelfAuthorized.sol
SignatureDecoder.sol
Singleton.sol
StorageAccessible.sol
DebugTransactionGuard.sol
DelegateCallTransactionGuard.sol
OnlyOwnersGuard.sol
ReentrancyTransactionGuard.sol
Migrate_1_3_0_to_1_2_0.sol
SafeMath.sol
CompatibilityFallbackHandler.sol
HandlerContext.sol
TokenCallbackHandler.sol
ERC1155TokenReceiver.sol
ERC721TokenReceiver.sol
ERC777TokensRecipient.sol
IERC165.sol
ISignatureValidator.sol
ViewStorageAccessible.sol
CreateCall.sol
MultiSend.sol
MultiSendCallOnly.sol
SafeStorage.sol
SignMessageLib.sol
IProxyCreationCallback.sol
SafeProxy.sol
SafeProxyFactory.sol
Downloads222

Chains

Authors

Gnosis Safe
Info
Docs
Source
ChefGPT
Expand
Share

Get Cookin'

Downloads222

Chains

Authors

Safe Contracts

npm version Build Status Coverage Status

:warning: This branch contains changes that are under development To use the latest audited version make sure to use the correct commit. The tagged versions that are used by the Safe team can be found in the releases.

Usage

Install requirements with yarn:

yarn

Testing

To run the tests:

yarn build
yarn test

Optionally, if you want to run the ERC-4337 compatibility test, it uses a live bundler and node, so it contains some pre-requisites:

  1. Define the environment variables:
ERC4337_TEST_BUNDLER_URL=
ERC4337_TEST_NODE_URL=
ERC4337_TEST_SINGLETON_ADDRESS=
ERC4337_TEST_SAFE_FACTORY_ADDRESS=
MNEMONIC=
  1. Pre-fund the executor account derived from the mnemonic with some Native Token to cover the deployment of an ERC4337 module and the pre-fund of the Safe for the test operation.

Deployments

A collection of the different Safe contract deployments and their addresses can be found in the Safe deployments repository.

To add support for a new network follow the steps of the Deploy section and create a PR in the Safe deployments repository.

Deploy

:warning: Make sure to use the correct commit when deploying the contracts. Any change (even comments) within the contract files will result in different addresses. The tagged versions that are used by the Safe team can be found in the releases.

Current version: The latest release is v1.3.0-libs.0 on the commit 767ef36

This will deploy the contracts deterministically and verify the contracts on etherscan using Solidity 0.7.6 by default.

Preparation:

  • Set MNEMONIC in .env
  • Set INFURA_KEY in .env
yarn deploy-all <network>

This will perform the following steps

yarn build
yarn hardhat --network <network> deploy
yarn hardhat --network <network> sourcify
yarn hardhat --network <network> etherscan-verify
yarn hardhat --network <network> local-verify

Custom Networks

It is possible to use the NODE_URL env var to connect to any EVM based network via an RPC endpoint. This connection then can be used with the custom network.

E.g. to deploy the Safe contract suite on that network you would run yarn deploy-all custom.

The resulting addresses should be on all networks the same.

Note: Address will vary if contract code is changed or a different Solidity version is used.

Replay protection (EIP-155)

Some networks require replay protection, making it incompatible with the default deployment process as it relies on a presigned transaction without replay protection (see https://github.com/Arachnid/deterministic-deployment-proxy).

Safe contracts use a different deterministic deployment proxy (https://github.com/safe-global/safe-singleton-factory). To make sure that the latest version of this package is installed, make sure to run yarn add @gnosis.pm/safe-singleton-factory before deployment. For more information, including how to deploy the factory to a new network, please refer to the factory repo.

Note: This will result in different addresses compared to hardhat's default deterministic deployment process.

Verify contract

This command will use the deployment artifacts to compile the contracts and compare them to the onchain code

yarn hardhat --network <network> local-verify

This command will upload the contract source to Etherescan

yarn hardhat --network <network> etherscan-verify

Documentation

Audits/ Formal Verification

Security and Liability

All contracts are WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

License

All smart contracts are released under LGPL-3.0

Collection of production code that is used in the Safe Ecosystem
Safe :
Most important concepts: - Threshold: Number of required confirmations for a Safe transaction. - Owners: List of addresses that control the Safe. They are the only ones that can add/remove owners, change the threshold and approve transactions. Managed in `OwnerManager`. - Transaction Hash: Hash of a transaction is calculated using the EIP-712 typed structured data hashing scheme. - Nonce: Each transaction should have a different nonce to prevent replay attacks. - Signature: A valid signature of an owner of the Safe for a transaction hash. - Guard: Guard is a contract that can execute pre- and post- transaction checks. Managed in `GuardManager`. - Modules: Modules are contracts that can be used to extend the write functionality of a Safe. Managed in `ModuleManager`. - Fallback: Fallback handler is a contract that can provide additional read-only functional for Safe. Managed in `FallbackManager`. Note: This version of the implementation contract doesn't emit events for the sake of gas efficiency and therefore requires a tracing node for indexing/ For the events-based implementation see `SafeL2.sol`.
addOwnerWithThreshold(address,uint256) :
This can only be done via a Safe transaction.
approveHash(bytes32) :
This can be used with a pre-approved hash transaction signature. IMPORTANT: The approved hash stays approved forever. There's no revocation mechanism, so it behaves similarly to ECDSA signatures
changeThreshold(uint256) :
This can only be done via a Safe transaction.
checkNSignatures(bytes32,bytes,bytes,uint256) :
Since the EIP-1271 does an external call, be mindful of reentrancy attacks.
disableModule(address,address) :
This can only be done via a Safe transaction.
domainSeparator() :
Returns the domain separator for this contract, as defined in the EIP-712 standard.
enableModule(address) :
This can only be done via a Safe transaction.
execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes) :
The fees are always transferred, even if the user transaction fails. This method doesn't perform any sanity check of the transaction, such as: - if the contract at `to` address has code or not - if the `gasToken` is a contract or not It is the responsibility of the caller to perform such checks.
execTransactionFromModule(address,uint256,bytes,uint8) :
Function is virtual to allow overriding for L2 singleton to emit an event for indexing.
removeOwner(address,address,uint256) :
This can only be done via a Safe transaction.
setFallbackHandler(address) :
Only fallback calls without value and with data will be forwarded. This can only be done via a Safe transaction. Cannot be set to the Safe itself.
setGuard(address) :
Set a guard that checks transactions before execution This can only be done via a Safe transaction. ⚠️ IMPORTANT: Since a guard has full power to block Safe transaction execution, a broken guard can cause a denial of service for the Safe. Make sure to carefully audit the guard code and design recovery mechanisms.
setup(address[],uint256,address,bytes,address,address,uint256,address) :
This method can only be called once. If a proxy was created without setting up, anyone can call setup and claim the proxy.
simulateAndRevert(address,bytes) :
Performs a delegatecall on a targetContract in the context of self. Internally reverts execution to avoid side effects (making it static). This method reverts with data equal to `abi.encode(bool(success), bytes(response))`. Specifically, the `returndata` after a call to this method will be: `success:bool || response.length:uint256 || response:bytes`.
swapOwner(address,address,address) :
This can only be done via a Safe transaction.
OwnerManager :
Uses a linked list to store the owners because the code generate by the solidity compiler is more efficient than using a dynamic array.
addOwnerWithThreshold(address,uint256) :
This can only be done via a Safe transaction.
changeThreshold(uint256) :
This can only be done via a Safe transaction.
removeOwner(address,address,uint256) :
This can only be done via a Safe transaction.
swapOwner(address,address,address) :
This can only be done via a Safe transaction.
DebugTransactionGuard :
This guard is only meant as a development tool and example
supportsInterface(bytes4) :
Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding EIP section https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified to learn more about how these ids are created. This function call must use less than 30 000 gas.
HandlerContext :
The fallback manager appends the following context to the calldata: 1. Fallback manager caller address (non-padded) based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/f8cc8b844a9f92f63dc55aa581f7d643a1bc5ac1/contracts/metatx/ERC2771Context.sol
ERC721TokenReceiver :
Note: the ERC-165 identifier for this interface is 0x150b7a02.
onERC721Received(address,address,uint256,bytes) :
The ERC721 smart contract calls this function on the recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return of other than the magic value MUST result in the transaction being reverted. Note: the contract address is always the message sender.
ERC777TokensRecipient :
Interface for contracts that will be called with the ERC777 token's `tokensReceived` method. The contract receiving the tokens must implement this interface in order to receive the tokens.
tokensReceived(address,address,address,uint256,bytes,bytes) :
Called by the ERC777 token contract after a successful transfer or a minting operation.
SafeStorage :
Should be always the first base contract of a library that is used with a Safe.
IProxyCreationCallback :
An interface for a contract that implements a callback function to be executed after the creation of a proxy instance.
proxyCreated(address,address,bytes,uint256) :
Function to be called after the creation of a SafeProxy instance.
Safe.sol
SafeL2.sol
SimulateTxAccessor.sol
Executor.sol
FallbackManager.sol
GuardManager.sol
ModuleManager.sol
OwnerManager.sol
Enum.sol
NativeCurrencyPaymentFallback.sol
SecuredTokenTransfer.sol
SelfAuthorized.sol
SignatureDecoder.sol
Singleton.sol
StorageAccessible.sol
DebugTransactionGuard.sol
DelegateCallTransactionGuard.sol
OnlyOwnersGuard.sol
ReentrancyTransactionGuard.sol
Migrate_1_3_0_to_1_2_0.sol
SafeMath.sol
CompatibilityFallbackHandler.sol
HandlerContext.sol
TokenCallbackHandler.sol
ERC1155TokenReceiver.sol
ERC721TokenReceiver.sol
ERC777TokensRecipient.sol
IERC165.sol
ISignatureValidator.sol
ViewStorageAccessible.sol
CreateCall.sol
MultiSend.sol
MultiSendCallOnly.sol
SafeStorage.sol
SignMessageLib.sol
IProxyCreationCallback.sol
SafeProxy.sol
SafeProxyFactory.sol